All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/41] DC Patches July 31, 2026
@ 2026-07-31 21:12 Roman.Li
  2026-07-31 21:12 ` [PATCH 03/41] drm/amd/display: Enable DCN6 init Roman.Li
                   ` (39 more replies)
  0 siblings, 40 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Roman Li

From: Roman Li <Roman.Li@amd.com>

This DC patchset brings improvements in multiple areas. In summary, we highlight:
 - Add KUnit tests for crtc functions
 - Enable DCN6
 - Fix ABM, CRC engine, MCM, writeback issues
 - Refactor stream validation.
  
Cc: Dan Wheeler <daniel.wheeler@amd.com> 

Alex Hung (2):
  drm/amd/display: Fix wb_info leak and NULL deref in writeback
  drm/amd/display: Fix more KUnit connector use-after-free bugs

Alvin Lee (1):
  drm/amd/display: Update BW bounding box unconditionally for DCN6

Aurabindo Pillai (5):
  drm/amd: Add DCN6 register headers
  drm/amd/display: Add new sources for DCN6
  drm/amd/display: Enable DCN6 init
  drm/amd/display: Dependent changes for DCN6
  drm/amd/display: Enable DCN6 sources compilation

Bhawanpreet Lakha (12):
  drm/amd/display: Add KUnit tests for more crtc functions
  drm/amd/display: Add vblank handling tests for crtc
  drm/amd/display: Add idle worker tests for crtc
  drm/amd/display: Add active plane count tests for crtc
  drm/amd/display: Add KUnit test for crtc vblank event completion
  drm/amd/display: Add KUnit tests for crtc set_vupdate_irq
  drm/amd/display: Add KUnit tests for crtc set_static_screen_optimze
  drm/amd/display: Add KUnit tests for crtc set_vblank
  drm/amd/display: Cover crtc set_vblank workqueue branch
  drm/amd/display: Cover crtc vblank IPS self-refresh restore
  drm/amd/display: Cover crtc vblank restore replay-supported path
  drm/amd/display: Cover crtc destroy_state stream release

Charlene Liu (1):
  drm/amd/display: Ensure dtbclk is enabled

Fangzhi Zuo (1):
  drm/amd/display: Gate HDMI FRL status polling on active FRL link rate

Harry VanZyllDeJong (1):
  drm/amd/display: Update VRR info packet to support 12-bit refresh
    rates

Harry Wentland (2):
  drm/amd/display: Resize MST HDCP per-connector arrays to 32
  drm/amd/display: Bounds-check connector->index in dm_dp_mst_get_modes

Iswara Nagulendran (1):
  drm/amd/display: Fix ABM over VABC

Ivan Lipski (3):
  drm/amd/display: Refactor stream validation
  drm/amd/display: Unify force_yuv debugfs into force_yuv_pixel_format
  drm/amd/display: Align connector KUnit tests with stream validation
    refactor

Karthi Kandasamy (1):
  drm/amd/display: Fix seamless mode switch not triggering for HDR to
    SDR transition

Matthew Stewart (1):
  drm/amd/display: Add missing DCN42B register defines

Rafal Ostrowski (1):
  drm/amd/display: Migrate color manager HW and fix MCM blend LUT issues

Relja Vojvodic (2):
  drm/amd/display: switch max FFE level cap based on FRL link rate
  drm/amd/display: Add FFE level defaults

Roman Li (1):
  drm/amd/display: Remove duplicate in tests/Makefile

Sung-huai Wang (1):
  drm/amd/display: Increase fclk change latency on dcn351

Taimur Hassan (2):
  drm/amd/display: Add missing DMUB CACP and PR definitions
  drm/amd/display: Promote DC to 3.2.392

Wayne Lin (3):
  drm/amd/display: Add missing OTG_CRC1_SELECT mask for DCN3.2
  drm/amd/display: Fix CRC engine 1 enable/disable on DCN3.1.2+
  drm/amd/display: Configure all CRC engines in pipe CRC source path

 drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c |     1 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |    31 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |     2 -
 .../amd/display/amdgpu_dm/amdgpu_dm_audio.h   |     2 +-
 .../display/amdgpu_dm/amdgpu_dm_connector.c   |   289 +-
 .../display/amdgpu_dm/amdgpu_dm_connector.h   |     8 +-
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c |    13 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |    25 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.h    |     9 +
 .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c |    57 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_dmub.c    |    10 +
 .../amd/display/amdgpu_dm/amdgpu_dm_dmub.h    |     1 +
 .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c    |    10 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.h    |    10 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |     6 +
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |     3 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |     9 +-
 .../drm/amd/display/amdgpu_dm/tests/Makefile  |     1 -
 .../tests/amdgpu_dm_connector_test.c          |   163 +-
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     |  1436 +
 .../amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c |    29 +
 .../tests/amdgpu_dm_kunit_test_helpers.h      |     3 +
 .../display/dc/bios/command_table_helper2.c   |     1 +
 .../gpu/drm/amd/display/dc/clk_mgr/Makefile   |     9 +
 .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c  |    15 +
 .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c  |    28 +-
 .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h  |     1 +
 .../drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h |   389 +
 .../display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c  |  1673 +
 .../display/dc/clk_mgr/dcn60/dcn60_clk_mgr.h  |   150 +
 .../dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.c  |   369 +
 .../dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.h  |    35 +
 drivers/gpu/drm/amd/display/dc/core/dc.c      |    76 +-
 .../drm/amd/display/dc/core/dc_hw_sequencer.c |   428 +
 .../gpu/drm/amd/display/dc/core/dc_resource.c |    47 +
 .../gpu/drm/amd/display/dc/core/dc_state.c    |    12 +
 .../gpu/drm/amd/display/dc/core/dc_stream.c   |    27 +-
 drivers/gpu/drm/amd/display/dc/dc.h           |    41 +-
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c  |    44 +
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h  |    23 +
 drivers/gpu/drm/amd/display/dc/dc_helper.c    |     2 +
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |    53 +-
 .../gpu/drm/amd/display/dc/dc_spl_translate.c |    32 +-
 .../gpu/drm/amd/display/dc/dc_state_priv.h    |     1 +
 drivers/gpu/drm/amd/display/dc/dc_stream.h    |     5 +
 drivers/gpu/drm/amd/display/dc/dc_types.h     |    13 +-
 drivers/gpu/drm/amd/display/dc/dccg/Makefile  |     8 +
 .../amd/display/dc/dccg/dcn20/dcn20_dccg.h    |    10 +
 .../amd/display/dc/dccg/dcn60/dcn60_dccg.c    |   187 +
 .../amd/display/dc/dccg/dcn60/dcn60_dccg.h    |   182 +
 .../drm/amd/display/dc/dce/dce_clock_source.c |    28 +
 .../drm/amd/display/dc/dce/dce_clock_source.h |     9 +
 drivers/gpu/drm/amd/display/dc/dio/Makefile   |     8 +
 .../display/dc/dio/dcn10/dcn10_link_encoder.h |    16 +
 .../dc/dio/dcn401/dcn401_dio_link_encoder.c   |    15 +
 .../dc/dio/dcn401/dcn401_dio_link_encoder.h   |    10 +
 .../dc/dio/dcn60/dcn60_dio_link_encoder.c     |   373 +
 .../dc/dio/dcn60/dcn60_dio_link_encoder.h     |    43 +
 .../dc/dio/dcn60/dcn60_dio_stream_encoder.c   |   538 +
 .../dc/dio/dcn60/dcn60_dio_stream_encoder.h   |   181 +
 drivers/gpu/drm/amd/display/dc/dm_helpers.h   |     8 +
 .../amd/display/dc/dml/dcn351/dcn351_fpu.c    |     4 +-
 .../gpu/drm/amd/display/dc/dml2_0/Makefile    |    25 +
 .../dml2_0/dml21/dml21_translation_helper.c   |    57 +-
 .../amd/display/dc/dml2_0/dml21/dml21_utils.c |   129 +-
 .../dml21/inc/bounding_boxes/dcn5_soc_bb.h    |    36 +
 .../dml21/inc/bounding_boxes/dcn6_soc_bb.h    |   229 +
 .../bounding_boxes/utm_qos_model_dchub_v1.h   |   109 +
 .../bounding_boxes/utm_qos_model_dchub_v2.h   |   122 +
 .../bounding_boxes/utm_qos_model_dchub_v3.h   |    53 +
 .../inc/bounding_boxes/utm_qos_model_types.h  |    51 +
 .../dc/dml2_0/dml21/inc/dml_dmub_cmd.h        |   502 +
 .../dml21/inc/dml_top_display_cfg_types.h     |    10 +
 .../dml21/inc/dml_top_soc_parameter_types.h   |     2 +
 .../dc/dml2_0/dml21/inc/dml_top_types.h       |    45 +
 .../dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.c |   152 +
 .../dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.h |     9 +
 .../dml21/src/dml2_cga/dml2_cga_factory.c     |    38 +
 .../dml21/src/dml2_cga/dml2_cga_factory.h     |     9 +
 .../dml2_core_calcs_dsc_shared_types.h        |    32 +
 .../src/dml2_core/dml2_core_dcn4_calcs.c      |     1 +
 .../dml2_core/dml2_core_dcn5_calcs_dchub.c    |  5893 ++
 .../dml2_core/dml2_core_dcn5_calcs_dchub.h    |   426 +
 .../dml2_core_dcn5_calcs_display_pipe.c       |  1029 +
 .../dml2_core_dcn5_calcs_display_pipe.h       |   151 +
 .../dml2_core_dcn5_calcs_dsc_latency.c        |   501 +
 .../dml2_core_dcn5_calcs_dsc_latency.h        |    23 +
 .../dml2_core_dcn5_funcs_initialize.c         |    78 +
 .../dml2_core_dcn5_funcs_initialize.h         |    12 +
 .../dml2_core_dcn5_funcs_mode_programming.c   |  1791 +
 .../dml2_core_dcn5_funcs_mode_programming.h   |    11 +
 .../dml2_core_dcn5_funcs_mode_support.c       |  2957 +
 .../dml2_core_dcn5_funcs_mode_support.h       |    11 +
 .../src/dml2_core/dml2_core_dcn6_calcs.c      |    11 +
 .../src/dml2_core/dml2_core_dcn6_calcs.h      |     8 +
 .../dml2_core/dml2_core_dcn6_calcs_dchub.c    |  1951 +
 .../dml2_core/dml2_core_dcn6_calcs_dchub.h    |   101 +
 .../dml2_core_dcn6_funcs_initialize.c         |   165 +
 .../dml2_core_dcn6_funcs_initialize.h         |    12 +
 .../dml2_core_dcn6_funcs_mode_programming.c   |  1389 +
 .../dml2_core_dcn6_funcs_mode_programming.h   |    11 +
 .../dml2_core_dcn6_funcs_mode_support.c       |  4277 ++
 .../dml2_core_dcn6_funcs_mode_support.h       |    11 +
 .../dml21/src/dml2_core/dml2_core_factory.c   |    25 +
 .../src/dml2_core/dml2_core_shared_types.h    |   160 +
 .../dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c      |     1 -
 .../dml21/src/dml2_dpmm/dml2_dpmm_dcn5.c      |   449 +
 .../dml21/src/dml2_dpmm/dml2_dpmm_dcn5.h      |    19 +
 .../dml21/src/dml2_dpmm/dml2_dpmm_factory.c   |    12 +
 .../dml21/src/dml2_mcg/dml2_mcg_factory.c     |     5 +
 .../dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c  |    57 +
 .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.c |   522 +
 .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.h |    21 +
 .../dml2_pmo/dml2_pmo_dcn5_stage_optimizers.c |  2228 +
 .../dml2_pmo/dml2_pmo_dcn5_stage_optimizers.h |    97 +
 .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.c |   506 +
 .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.h |    22 +
 .../dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c |  1789 +
 .../dml2_pmo/dml2_pmo_dcn6_stage_optimizers.h |    17 +
 .../dml21/src/dml2_pmo/dml2_pmo_factory.c     |    34 +
 .../alternate_pstate_shared_lib.c             |  1078 +
 .../alternate_pstate_shared_lib.h             |   109 +
 .../dml21/src/dml2_top/dml2_top_interfaces.c  |     7 +
 .../dml2_0/dml21/src/dml2_top/dml2_top_utm.c  |   394 +
 .../dml2_0/dml21/src/dml2_top/dml2_top_utm.h  |     9 +
 .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.c    |   144 +
 .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.h    |    11 +
 .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c    |   405 +
 .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.h    |    12 +
 .../dml2_utm_soc_bb/dml2_utm_soc_bb_factory.c |    29 +
 .../dml2_utm_soc_bb/dml2_utm_soc_bb_factory.h |    11 +
 .../src/inc/dml2_internal_shared_types.h      |   485 +
 .../drm/amd/display/dc/dml2_0/dml2_wrapper.h  |     8 +
 drivers/gpu/drm/amd/display/dc/dpp/Makefile   |    17 +
 .../amd/display/dc/dpp/dcn401/dcn401_dpp.h    |    41 +
 .../display/dc/dpp/dcn401/dcn401_dpp_dscl.c   |    26 +-
 .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c  |     7 +-
 .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h  |     6 +
 .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c  |   391 +
 .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h  |    86 +
 .../drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c  |   346 +
 .../drm/amd/display/dc/dpp/dcn60/dcn60_dpp.h  |   525 +
 .../amd/display/dc/dpp/dcn60/dcn60_dpp_dscl.c |   315 +
 drivers/gpu/drm/amd/display/dc/dsc/Makefile   |     7 +
 .../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c  |   447 +
 .../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h  |   248 +
 drivers/gpu/drm/amd/display/dc/gpio/Makefile  |    10 +
 .../display/dc/gpio/dcn60/hw_factory_dcn60.c  |   228 +
 .../display/dc/gpio/dcn60/hw_factory_dcn60.h  |    11 +
 .../dc/gpio/dcn60/hw_translate_dcn60.c        |   168 +
 .../dc/gpio/dcn60/hw_translate_dcn60.h        |    13 +
 .../gpu/drm/amd/display/dc/gpio/ddc_regs.h    |    15 +
 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c  |   302 +
 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h  |    28 +
 .../gpu/drm/amd/display/dc/gpio/hw_factory.c  |     4 +
 .../drm/amd/display/dc/gpio/hw_translate.c    |     4 +
 .../gpu/drm/amd/display/dc/hdcp/hdcp_msg.c    |     9 +
 drivers/gpu/drm/amd/display/dc/hpo/Makefile   |     8 +
 .../hpo/dcn31/dcn31_hpo_dp_stream_encoder.h   |    47 -
 .../dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.c |   114 +
 .../dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.h |    18 +
 .../hpo/dcn60/dcn60_hpo_frl_stream_encoder.c  |   358 +
 .../hpo/dcn60/dcn60_hpo_frl_stream_encoder.h  |    32 +
 .../gpu/drm/amd/display/dc/hubbub/Makefile    |     8 +
 .../display/dc/hubbub/dcn10/dcn10_hubbub.h    |   108 +
 .../display/dc/hubbub/dcn60/dcn60_hubbub.c    |  1816 +
 .../display/dc/hubbub/dcn60/dcn60_hubbub.h    |   207 +
 drivers/gpu/drm/amd/display/dc/hubp/Makefile  |    16 +
 .../amd/display/dc/hubp/dcn20/dcn20_hubp.h    |    29 +
 .../amd/display/dc/hubp/dcn401/dcn401_hubp.c  |   201 +-
 .../amd/display/dc/hubp/dcn401/dcn401_hubp.h  |    23 +-
 .../amd/display/dc/hubp/dcn42/dcn42_hubp.c    |    78 +-
 .../amd/display/dc/hubp/dcn42/dcn42_hubp.h    |    10 +-
 .../amd/display/dc/hubp/dcn50/dcn50_hubp.c    |   532 +
 .../amd/display/dc/hubp/dcn50/dcn50_hubp.h    |    48 +
 .../amd/display/dc/hubp/dcn60/dcn60_hubp.c    |   472 +
 .../amd/display/dc/hubp/dcn60/dcn60_hubp.h    |   272 +
 drivers/gpu/drm/amd/display/dc/hwss/Makefile  |    16 +
 .../drm/amd/display/dc/hwss/dce/dce_hwseq.h   |     9 +
 .../amd/display/dc/hwss/dce110/dce110_hwseq.c |    21 +-
 .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c   |     3 +-
 .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c   |     3 +-
 .../amd/display/dc/hwss/dcn30/dcn30_hwseq.c   |     3 +-
 .../amd/display/dc/hwss/dcn31/dcn31_hwseq.c   |    21 +-
 .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c   |     5 +-
 .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c   |     8 +-
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c |   483 +-
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.h |     7 +-
 .../amd/display/dc/hwss/dcn401/dcn401_init.c  |     1 -
 .../amd/display/dc/hwss/dcn42/dcn42_hwseq.c   |   488 +-
 .../amd/display/dc/hwss/dcn42/dcn42_hwseq.h   |     6 -
 .../amd/display/dc/hwss/dcn42/dcn42_init.c    |     2 -
 .../amd/display/dc/hwss/dcn50/dcn50_hwseq.c   |   759 +
 .../amd/display/dc/hwss/dcn50/dcn50_hwseq.h   |    32 +
 .../amd/display/dc/hwss/dcn60/dcn60_hwseq.c   |  1164 +
 .../amd/display/dc/hwss/dcn60/dcn60_hwseq.h   |    32 +
 .../amd/display/dc/hwss/dcn60/dcn60_init.c    |   181 +
 .../amd/display/dc/hwss/dcn60/dcn60_init.h    |    12 +
 .../drm/amd/display/dc/hwss/hw_sequencer.h    |    19 +-
 .../display/dc/hwss/hw_sequencer_private.h    |     5 -
 .../gpu/drm/amd/display/dc/inc/core_types.h   |     1 +
 .../gpu/drm/amd/display/dc/inc/hw/clk_mgr.h   |     1 +
 .../amd/display/dc/inc/hw/clk_mgr_internal.h  |    22 +
 .../amd/display/dc/inc/hw/cursor_reg_cache.h  |     3 +-
 drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h   |     7 +
 drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h  |    35 +-
 .../drm/amd/display/dc/inc/hw/link_encoder.h  |     6 +
 drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h   |    81 +-
 .../gpu/drm/amd/display/dc/inc/hw/transform.h |     1 +
 drivers/gpu/drm/amd/display/dc/inc/resource.h |     2 +
 drivers/gpu/drm/amd/display/dc/irq/Makefile   |     9 +
 .../display/dc/irq/dcn60/irq_service_dcn60.c  |   417 +
 .../display/dc/irq/dcn60/irq_service_dcn60.h  |    12 +
 .../drm/amd/display/dc/link/link_detection.c  |    29 +
 .../drm/amd/display/dc/link/link_factory.c    |     5 +
 .../amd/display/dc/link/protocols/link_ddc.c  |     8 +
 .../display/dc/link/protocols/link_hdmi_frl.c |    23 +-
 drivers/gpu/drm/amd/display/dc/mpc/Makefile   |     8 +
 .../amd/display/dc/mpc/dcn401/dcn401_mpc.c    |   177 +-
 .../amd/display/dc/mpc/dcn401/dcn401_mpc.h    |    25 +-
 .../drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c  |   405 +-
 .../drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h  |    55 +-
 .../drm/amd/display/dc/mpc/dcn60/dcn60_mpc.c  |   330 +
 .../drm/amd/display/dc/mpc/dcn60/dcn60_mpc.h  |   472 +
 drivers/gpu/drm/amd/display/dc/opp/Makefile   |     8 +
 .../drm/amd/display/dc/opp/dcn60/dcn60_opp.c  |    25 +
 .../drm/amd/display/dc/opp/dcn60/dcn60_opp.h  |    64 +
 drivers/gpu/drm/amd/display/dc/optc/Makefile  |     9 +
 .../amd/display/dc/optc/dcn10/dcn10_optc.c    |    36 +-
 .../amd/display/dc/optc/dcn10/dcn10_optc.h    |     3 +-
 .../amd/display/dc/optc/dcn31/dcn31_optc.h    |     4 +
 .../amd/display/dc/optc/dcn314/dcn314_optc.h  |     1 +
 .../amd/display/dc/optc/dcn32/dcn32_optc.h    |     2 +
 .../amd/display/dc/optc/dcn35/dcn35_optc.c    |    26 +-
 .../amd/display/dc/optc/dcn401/dcn401_optc.h  |     1 +
 .../amd/display/dc/optc/dcn42/dcn42_optc.c    |     9 +-
 .../amd/display/dc/optc/dcn42/dcn42_optc.h    |     4 +
 .../amd/display/dc/optc/dcn60/dcn60_optc.c    |   107 +
 .../amd/display/dc/optc/dcn60/dcn60_optc.h    |   178 +
 .../gpu/drm/amd/display/dc/resource/Makefile  |    10 +
 .../dc/resource/dcn10/dcn10_resource.c        |     1 +
 .../dc/resource/dcn20/dcn20_resource.c        |     1 +
 .../dc/resource/dcn201/dcn201_resource.c      |     1 +
 .../dc/resource/dcn21/dcn21_resource.c        |     1 +
 .../dc/resource/dcn30/dcn30_resource.c        |     2 +
 .../dc/resource/dcn301/dcn301_resource.c      |     1 +
 .../dc/resource/dcn302/dcn302_resource.c      |     2 +
 .../dc/resource/dcn303/dcn303_resource.c      |     2 +
 .../dc/resource/dcn31/dcn31_resource.c        |     1 +
 .../dc/resource/dcn314/dcn314_resource.c      |     2 +
 .../dc/resource/dcn315/dcn315_resource.c      |     6 +-
 .../dc/resource/dcn316/dcn316_resource.c      |     5 +-
 .../dc/resource/dcn32/dcn32_resource.c        |     2 +
 .../dc/resource/dcn321/dcn321_resource.c      |     2 +
 .../dc/resource/dcn35/dcn35_resource.c        |     2 +
 .../dc/resource/dcn351/dcn351_resource.c      |     2 +
 .../dc/resource/dcn36/dcn36_resource.c        |     2 +
 .../dc/resource/dcn401/dcn401_resource.c      |    34 +-
 .../dc/resource/dcn401/dcn401_resource.h      |     4 +
 .../dc/resource/dcn42/dcn42_resource.c        |     3 +
 .../dc/resource/dcn42b/dcn42b_resource.c      |    20 +-
 .../dc/resource/dcn60/dcn60_resource.c        |  2377 +
 .../dc/resource/dcn60/dcn60_resource.h        |   676 +
 .../display/dc/soc_and_ip_translator/Makefile |     3 +
 .../dcn60/dcn60_soc_and_ip_translator.c       |   117 +
 .../dcn60/dcn60_soc_and_ip_translator.h       |    16 +
 .../soc_and_ip_translator.c                   |     4 +
 drivers/gpu/drm/amd/display/dmub/dmub_srv.h   |     5 +
 .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   |   229 +-
 drivers/gpu/drm/amd/display/dmub/src/Makefile |     1 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn60.c |   732 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn60.h |   303 +
 .../gpu/drm/amd/display/dmub/src/dmub_srv.c   |    52 +
 .../gpu/drm/amd/display/include/dal_asic_id.h |    18 +
 .../gpu/drm/amd/display/include/dal_types.h   |     1 +
 .../amd/display/modules/freesync/freesync.c   |     8 +-
 .../drm/amd/display/modules/power/power_abm.c |   215 +-
 .../amd/display/modules/power/power_helpers.h |     9 +
 .../drm/amd/display/modules/power/power_psr.c |     7 +
 .../amd/display/modules/power/power_replay.c  |     7 +
 .../include/asic_reg/dcn/dcn_6_0_0_offset.h   | 15799 +++++
 .../include/asic_reg/dcn/dcn_6_0_0_sh_mask.h  | 58556 ++++++++++++++++
 .../include/asic_reg/dpcs/dpcs_6_0_0_offset.h |    47 +
 .../asic_reg/dpcs/dpcs_6_0_0_sh_mask.h        |    55 +
 .../asic_reg/mmhub/mmhub_5_0_1_offset.h       |    17 +
 .../asic_reg/mmhub/mmhub_5_0_1_sh_mask.h      |    17 +
 286 files changed, 129427 insertions(+), 1800 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn5_soc_bb.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn6_soc_bb.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos_model_dchub_v1.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos_model_dchub_v2.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos_model_dchub_v3.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos_model_types.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_dmub_cmd.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_factory.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_factory.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_calcs_dsc_shared_types.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_dchub.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_dchub.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_display_pipe.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_display_pipe.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_dsc_latency.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_dsc_latency.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_initialize.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_initialize.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_programming.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_programming.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_support.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_support.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_calcs.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_calcs.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_calcs_dchub.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_calcs_dchub.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_initialize.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_initialize.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_programming.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_programming.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_support.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_support.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn5.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn5.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5_stage_optimizers.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5_stage_optimizers.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stage_optimizers.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_utm.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_utm.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_factory.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_factory.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp_dscl.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_factory_dcn60.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_factory_dcn60.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_translate_dcn60.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_translate_dcn60.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hubbub/dcn60/dcn60_hubbub.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hubbub/dcn60/dcn60_hubbub.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn50/dcn50_hubp.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn50/dcn50_hubp.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dcn60/irq_service_dcn60.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dcn60/irq_service_dcn60.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/opp/dcn60/dcn60_opp.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/opp/dcn60/dcn60_opp.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn60/dcn60_optc.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn60/dcn60_optc.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn60/dcn60_soc_and_ip_translator.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn60/dcn60_soc_and_ip_translator.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.c
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.h
 create mode 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_6_0_0_offset.h
 create mode 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_6_0_0_sh_mask.h
 create mode 100644 drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_6_0_0_offset.h
 create mode 100644 drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_6_0_0_sh_mask.h
 create mode 100644 drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_5_0_1_offset.h
 create mode 100644 drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_5_0_1_sh_mask.h

-- 
2.34.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* [PATCH 03/41] drm/amd/display: Enable DCN6 init
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 04/41] drm/amd/display: Dependent changes for DCN6 Roman.Li
                   ` (38 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Roman Li

From: Aurabindo Pillai <aurabindo.pillai@amd.com>

Add hooks in various entry points to perform hw/sw init for DCN6 asic

Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: Roman Li <Roman.Li@amd.com>
Reviewed-by: Ivan Lipski <ivan.lipski@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c     |  1 +
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 15 +++++++++------
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c    | 10 ++++++++++
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.h    |  1 +
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c   |  9 +++++++--
 .../amd/display/dc/bios/command_table_helper2.c   |  1 +
 drivers/gpu/drm/amd/display/include/dal_types.h   |  1 +
 7 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index cf9c4b8df28b..45762096b20b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -2658,6 +2658,7 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
 		case IP_VERSION(4, 1, 0):
 		case IP_VERSION(4, 2, 0):
 		case IP_VERSION(4, 2, 1):
+		case IP_VERSION(6, 0, 0):
 			/* TODO: Fix IP version. DC code expects version 4.0.1 */
 			if (adev->ip_versions[DCE_HWIP][0] == IP_VERSION(4, 1, 0))
 				adev->ip_versions[DCE_HWIP][0] = IP_VERSION(4, 0, 1);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index df6b59fb8d0d..0dcf829c1d07 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1011,6 +1011,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
 		case IP_VERSION(4, 0, 1):
 		case IP_VERSION(4, 2, 0):
 		case IP_VERSION(4, 2, 1):
+		case IP_VERSION(6, 0, 0):
 			return 0;
 		default:
 			break;
@@ -2410,6 +2411,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
 	case IP_VERSION(4, 0, 1):
 	case IP_VERSION(4, 2, 0):
 	case IP_VERSION(4, 2, 1):
+	case IP_VERSION(6, 0, 0):
 		if (amdgpu_dm_register_outbox_irq_handlers(dm->adev)) {
 			drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n");
 			goto fail;
@@ -2436,6 +2438,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
 		case IP_VERSION(4, 0, 1):
 		case IP_VERSION(4, 2, 0):
 		case IP_VERSION(4, 2, 1):
+		case IP_VERSION(6, 0, 0):
 			psr_feature_enabled = true;
 			break;
 		default:
@@ -2455,6 +2458,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
 		case IP_VERSION(3, 6, 0):
 		case IP_VERSION(4, 2, 0):
 		case IP_VERSION(4, 2, 1):
+		case IP_VERSION(6, 0, 0):
 			replay_feature_enabled = true;
 			break;
 
@@ -2617,6 +2621,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
 		case IP_VERSION(4, 0, 1):
 		case IP_VERSION(4, 2, 0):
 		case IP_VERSION(4, 2, 1):
+		case IP_VERSION(6, 0, 0):
 			if (amdgpu_dm_dcn10_register_irq_handlers(dm->adev)) {
 				drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n");
 				goto fail;
@@ -2829,6 +2834,7 @@ static int dm_early_init(struct amdgpu_ip_block *ip_block)
 		case IP_VERSION(4, 0, 1):
 		case IP_VERSION(4, 2, 0):
 		case IP_VERSION(4, 2, 1):
+		case IP_VERSION(6, 0, 0):
 			adev->mode_info.num_crtc = 4;
 			adev->mode_info.num_hpd = 4;
 			adev->mode_info.num_dig = 4;
@@ -6320,12 +6326,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 		if (dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
 			continue;
 
-		/* Check if rotation or scaling is enabled on DCN401 */
-		if ((drm_plane_mask(crtc->cursor) &
-		     new_crtc_state->plane_mask) &&
-		    (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 1) ||
-		     amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0) ||
-		     amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1))) {
+		/* Check if rotation or scaling is enabled on DCN 4x and above */
+		if ((drm_plane_mask(crtc->cursor) & new_crtc_state->plane_mask) &&
+		    (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(4, 0, 1))) {
 			new_cursor_state = drm_atomic_get_new_plane_state(state, crtc->cursor);
 
 			is_rotated = new_cursor_state &&
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c
index 8e35d9ec22d6..9ff25bc8ee5a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c
@@ -63,6 +63,7 @@ MODULE_FIRMWARE(FIRMWARE_DCN_36_DMUB);
 MODULE_FIRMWARE(FIRMWARE_DCN_401_DMUB);
 MODULE_FIRMWARE(FIRMWARE_DCN_42_DMUB);
 MODULE_FIRMWARE(FIRMWARE_DCN_42B_DMUB);
+MODULE_FIRMWARE(FIRMWARE_DCN_60_DMUB);
 
 /**
  * dm_dmub_aux_setconfig_callback - Callback for AUX or SET_CONFIG command.
@@ -408,6 +409,9 @@ STATIC_IFN_KUNIT void *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev
 	case IP_VERSION(4, 2, 1):
 		bb_size = sizeof(struct dml2_soc_bb);
 		break;
+	case IP_VERSION(6, 0, 0):
+		bb_size = sizeof(struct dmub_soc_bb_params);
+		break;
 	default:
 		return NULL;
 	}
@@ -560,6 +564,9 @@ int dm_dmub_sw_init(struct amdgpu_device *adev)
 	case IP_VERSION(4, 2, 1):
 		dmub_asic = DMUB_ASIC_DCN42B;
 		break;
+	case IP_VERSION(6, 0, 0):
+		dmub_asic = DMUB_ASIC_DCN60;
+		break;
 	default:
 		/* ASIC doesn't support DMUB. */
 		return 0;
@@ -752,6 +759,9 @@ int dm_init_microcode(struct amdgpu_device *adev)
 	case IP_VERSION(4, 2, 1):
 		fw_name_dmub = FIRMWARE_DCN_42B_DMUB;
 		break;
+	case IP_VERSION(6, 0, 0):
+		fw_name_dmub = FIRMWARE_DCN_60_DMUB;
+		break;
 	default:
 		/* ASIC doesn't support DMUB. */
 		return 0;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.h
index c53728d1c131..31d5f8c265c0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.h
@@ -62,6 +62,7 @@ int dm_init_microcode(struct amdgpu_device *adev);
 #define FIRMWARE_DCN_401_DMUB		"amdgpu/dcn_4_0_1_dmcub.bin"
 #define FIRMWARE_DCN_42_DMUB		"amdgpu/dcn_4_2_dmcub.bin"
 #define FIRMWARE_DCN_42B_DMUB		"amdgpu/dcn_4_2_1_dmcub.bin"
+#define FIRMWARE_DCN_60_DMUB		"amdgpu/dcn_6_0_0_dmcub.bin"
 #define FIRMWARE_RAVEN_DMCU		"amdgpu/raven_dmcu.bin"
 #define FIRMWARE_NAVI12_DMCU		"amdgpu/navi12_dmcu.bin"
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index 0c6f0cac666e..824ef3ce5de0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -144,7 +144,8 @@ void amdgpu_dm_plane_fill_blending_from_plane_state(const struct drm_plane_state
 		 * other ASICs use an 8-bit field. The DRM plane alpha is
 		 * 16-bit, so scale it down to the width the hardware expects.
 		 */
-		if (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0))
+		if (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0)
+		    || amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(6, 0, 0))
 			*global_alpha_value = plane_state->alpha >> 4;
 		else
 			*global_alpha_value = plane_state->alpha >> 8;
@@ -316,6 +317,7 @@ STATIC_IFN_KUNIT int amdgpu_dm_plane_validate_dcc(struct amdgpu_device *adev,
 		return 0;
 
 	if (adev->family != AMDGPU_FAMILY_GC_12_0_0 &&
+	    adev->family != AMDGPU_FAMILY_GC_13_0_1 &&
 	    format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
 		return -EINVAL;
 
@@ -1047,6 +1049,8 @@ STATIC_IFN_KUNIT int amdgpu_dm_plane_get_plane_modifiers(struct amdgpu_device *a
 		amdgpu_dm_plane_add_gfx11_modifiers(adev, mods, &size, &capacity);
 		break;
 	case AMDGPU_FAMILY_GC_12_0_0:
+	case AMDGPU_FAMILY_GC_13_0_1:
+		/* GFX13 (DCN6) shares the GFX12 tiling/DCC binary modifier format. */
 		amdgpu_dm_plane_add_gfx12_modifiers(adev, mods, &size, &capacity);
 		break;
 	}
@@ -1187,7 +1191,8 @@ int amdgpu_dm_plane_fill_plane_buffer_attributes(struct amdgpu_device *adev,
 			upper_32_bits(chroma_addr);
 	}
 
-	if (adev->family == AMDGPU_FAMILY_GC_12_0_0) {
+	if (adev->family == AMDGPU_FAMILY_GC_12_0_0
+	    || adev->family == AMDGPU_FAMILY_GC_13_0_1) {
 		ret = amdgpu_dm_plane_fill_gfx12_attrs_from_modifiers(adev, afb, format,
 										 rotation, plane_size,
 										 tiling_info, dcc,
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
index 902f06ac43c6..9ae5cf42754a 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c
@@ -86,6 +86,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2(
 	case DCN_VERSION_4_01:
 	case DCN_VERSION_4_2:
 	case DCN_VERSION_4_2B:
+	case DCN_VERSION_6_0:
 		*h = dal_cmd_tbl_helper_dce112_get_table2();
 		return true;
 
diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h
index f77fc367eab1..d67fe0a64418 100644
--- a/drivers/gpu/drm/amd/display/include/dal_types.h
+++ b/drivers/gpu/drm/amd/display/include/dal_types.h
@@ -67,6 +67,7 @@ enum dce_version {
 	DCN_VERSION_4_01,
 	DCN_VERSION_4_2,
 	DCN_VERSION_4_2B,
+	DCN_VERSION_6_0,
 	DCN_VERSION_MAX
 };
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 04/41] drm/amd/display: Dependent changes for DCN6
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
  2026-07-31 21:12 ` [PATCH 03/41] drm/amd/display: Enable DCN6 init Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 05/41] drm/amd/display: Enable DCN6 sources compilation Roman.Li
                   ` (37 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Roman Li

From: Aurabindo Pillai <aurabindo.pillai@amd.com>

changes needed to enable DCN6 asic

Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: Roman Li <Roman.Li@amd.com>
Reviewed-by: Ivan Lipski <ivan.lipski@amd.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_audio.h   |   2 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |   6 +
 .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c  |  15 +
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  10 +-
 .../drm/amd/display/dc/core/dc_hw_sequencer.c | 410 +++++++++++++++
 .../gpu/drm/amd/display/dc/core/dc_resource.c |  47 ++
 .../gpu/drm/amd/display/dc/core/dc_state.c    |  12 +
 .../gpu/drm/amd/display/dc/core/dc_stream.c   |  24 +
 drivers/gpu/drm/amd/display/dc/dc.h           |  26 +-
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c  |  44 ++
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h  |  23 +
 drivers/gpu/drm/amd/display/dc/dc_helper.c    |   2 +
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |  53 +-
 .../gpu/drm/amd/display/dc/dc_spl_translate.c |  32 +-
 .../gpu/drm/amd/display/dc/dc_state_priv.h    |   1 +
 drivers/gpu/drm/amd/display/dc/dc_stream.h    |   5 +
 drivers/gpu/drm/amd/display/dc/dc_types.h     |  10 +
 .../amd/display/dc/dccg/dcn20/dcn20_dccg.h    |  10 +
 .../drm/amd/display/dc/dce/dce_clock_source.c |  24 +
 .../drm/amd/display/dc/dce/dce_clock_source.h |   9 +
 .../display/dc/dio/dcn10/dcn10_link_encoder.h |  16 +
 .../dc/dio/dcn401/dcn401_dio_link_encoder.c   |  15 +
 .../dc/dio/dcn401/dcn401_dio_link_encoder.h   |  10 +
 drivers/gpu/drm/amd/display/dc/dm_helpers.h   |   8 +
 .../dml2_0/dml21/dml21_translation_helper.c   |  57 +-
 .../amd/display/dc/dml2_0/dml21/dml21_utils.c | 129 ++++-
 .../dml21/inc/dml_top_display_cfg_types.h     |  10 +
 .../dml21/inc/dml_top_soc_parameter_types.h   |   2 +
 .../dc/dml2_0/dml21/inc/dml_top_types.h       |  45 ++
 .../src/dml2_core/dml2_core_dcn4_calcs.c      |   1 +
 .../dml21/src/dml2_core/dml2_core_factory.c   |  25 +
 .../src/dml2_core/dml2_core_shared_types.h    | 160 ++++++
 .../dml21/src/dml2_dpmm/dml2_dpmm_factory.c   |  12 +
 .../dml21/src/dml2_mcg/dml2_mcg_factory.c     |   5 +
 .../dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c  |  57 ++
 .../dml21/src/dml2_pmo/dml2_pmo_factory.c     |  34 ++
 .../dml21/src/dml2_top/dml2_top_interfaces.c  |   7 +
 .../src/inc/dml2_internal_shared_types.h      | 485 ++++++++++++++++++
 .../drm/amd/display/dc/dml2_0/dml2_wrapper.h  |   8 +
 .../amd/display/dc/dpp/dcn401/dcn401_dpp.h    |  41 ++
 .../display/dc/dpp/dcn401/dcn401_dpp_dscl.c   |  26 +-
 .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c  |   7 +-
 .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h  |   6 +
 .../gpu/drm/amd/display/dc/gpio/ddc_regs.h    |  15 +
 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c  | 302 +++++++++++
 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h  |  28 +
 .../gpu/drm/amd/display/dc/gpio/hw_factory.c  |   4 +
 .../drm/amd/display/dc/gpio/hw_translate.c    |   4 +
 .../gpu/drm/amd/display/dc/hdcp/hdcp_msg.c    |   9 +
 .../display/dc/hubbub/dcn10/dcn10_hubbub.h    | 108 ++++
 .../amd/display/dc/hubp/dcn20/dcn20_hubp.h    |  29 ++
 .../drm/amd/display/dc/hwss/dce/dce_hwseq.h   |   9 +
 .../amd/display/dc/hwss/dce110/dce110_hwseq.c |  11 +
 .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c   |   3 +-
 .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c   |   3 +-
 .../amd/display/dc/hwss/dcn30/dcn30_hwseq.c   |   3 +-
 .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c   |   5 +-
 .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c   |   1 +
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c |  32 ++
 .../drm/amd/display/dc/hwss/hw_sequencer.h    |  17 +
 .../gpu/drm/amd/display/dc/inc/core_types.h   |   1 +
 .../amd/display/dc/inc/hw/clk_mgr_internal.h  |  22 +
 .../amd/display/dc/inc/hw/cursor_reg_cache.h  |   3 +-
 drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h   |   7 +
 .../drm/amd/display/dc/inc/hw/link_encoder.h  |   6 +
 .../gpu/drm/amd/display/dc/inc/hw/transform.h |   1 +
 drivers/gpu/drm/amd/display/dc/inc/resource.h |   2 +
 .../drm/amd/display/dc/link/link_detection.c  |  29 ++
 .../drm/amd/display/dc/link/link_factory.c    |   5 +
 .../amd/display/dc/link/protocols/link_ddc.c  |   8 +
 .../display/dc/link/protocols/link_hdmi_frl.c |   5 +
 .../amd/display/dc/optc/dcn42/dcn42_optc.c    |   4 +-
 .../amd/display/dc/optc/dcn42/dcn42_optc.h    |   2 +
 .../dc/resource/dcn10/dcn10_resource.c        |   1 +
 .../dc/resource/dcn20/dcn20_resource.c        |   1 +
 .../dc/resource/dcn201/dcn201_resource.c      |   1 +
 .../dc/resource/dcn21/dcn21_resource.c        |   1 +
 .../dc/resource/dcn30/dcn30_resource.c        |   1 +
 .../dc/resource/dcn301/dcn301_resource.c      |   1 +
 .../dc/resource/dcn302/dcn302_resource.c      |   1 +
 .../dc/resource/dcn303/dcn303_resource.c      |   1 +
 .../dc/resource/dcn314/dcn314_resource.c      |   1 +
 .../dc/resource/dcn315/dcn315_resource.c      |   1 +
 .../dc/resource/dcn32/dcn32_resource.c        |   1 +
 .../dc/resource/dcn321/dcn321_resource.c      |   1 +
 .../dc/resource/dcn35/dcn35_resource.c        |   1 +
 .../dc/resource/dcn351/dcn351_resource.c      |   1 +
 .../dc/resource/dcn36/dcn36_resource.c        |   1 +
 .../dc/resource/dcn401/dcn401_resource.c      |  33 +-
 .../dc/resource/dcn401/dcn401_resource.h      |   4 +
 .../dc/resource/dcn42/dcn42_resource.c        |   1 +
 .../soc_and_ip_translator.c                   |   4 +
 drivers/gpu/drm/amd/display/dmub/dmub_srv.h   |   5 +
 .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   | 175 ++++++-
 .../gpu/drm/amd/display/dmub/src/dmub_srv.c   |  52 ++
 .../gpu/drm/amd/display/include/dal_asic_id.h |  18 +
 96 files changed, 2871 insertions(+), 45 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.h
index e57e2ed20d56..7ccb026ece56 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_audio.h
@@ -28,7 +28,7 @@
 
 struct amdgpu_device;
 struct drm_device;
-struct drm_atomic_state;
+struct drm_atomic_commit;
 struct drm_connector;
 struct audio_info;
 struct dc_sink;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index c720c319e795..d451082552e8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -1903,3 +1903,9 @@ void dm_helpers_mccs_vcp_set(struct dc_context *ctx, struct dc_link *link,
 }
 EXPORT_IF_KUNIT(dm_helpers_mccs_vcp_set);
 
+bool dm_helpers_submit_i2c_over_aux(struct ddc_service *ddc, uint32_t address, uint8_t offset,
+				    uint8_t *cmdBuffer, uint32_t len, bool read)
+{
+	//TODO: Implement this
+	return false;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
index 2a1353cb7e7d..e2148cb3b8ab 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c
@@ -50,6 +50,7 @@
 #include "dcn401/dcn401_clk_mgr.h"
 #include "dcn42/dcn42_clk_mgr.h"
 #include "dcn42b/dcn42b_clk_mgr.h"
+#include "dcn60/dcn60_clk_mgr.h"
 
 int clk_mgr_helper_get_active_display_cnt(
 		struct dc *dc,
@@ -387,6 +388,17 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
 		return &clk_mgr->base.base;
 	}
 	break;
+	case AMDGPU_FAMILY_GC_13_0_1: {
+		struct clk_mgr_internal *clk_mgr = dcn60_clk_mgr_construct(ctx, dccg);
+
+		if (clk_mgr == NULL) {
+			BREAK_TO_DEBUGGER();
+			return NULL;
+		}
+
+		return &clk_mgr->base;
+	}
+
 #endif	/* CONFIG_DRM_AMD_DC_FP */
 	default:
 		ASSERT(0); /* Unknown Asic */
@@ -451,6 +463,9 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base)
 	case AMDGPU_FAMILY_GC_11_5_4:
 		dcn42_clk_mgr_destroy(clk_mgr);
 		break;
+	case AMDGPU_FAMILY_GC_13_0_1:
+		dcn60_clk_mgr_destroy(clk_mgr);
+		break;
 
 	default:
 		break;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 6c1a8ecc2cb5..7f378b5e896c 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3099,7 +3099,8 @@ static struct dc_update_descriptor det_surface_update(
 			update_bits->gamut_remap_change ||
 			update_bits->input_csc_change ||
 			update_bits->cm_hist_change ||
-			update_bits->coeff_reduction_change)) {
+			update_bits->coeff_reduction_change ||
+			update_bits->cursor_csc_color_matrix_change)) {
 		elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
 	}
 	return overall_type;
@@ -3403,6 +3404,10 @@ static void copy_surface_update_to_plane(
 				srf_update->plane_info->dcc;
 		surface->layer_index =
 				srf_update->plane_info->layer_index;
+		surface->scaling_linearity =
+				srf_update->plane_info->scaling_linearity;
+		surface->cositing =
+				srf_update->plane_info->cositing;
 	}
 
 	if (srf_update->gamma) {
@@ -3658,6 +3663,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
 	if (update->sharpening_required)
 		stream->sharpening_required = *update->sharpening_required;
 
+	if (update->blending_linearity)
+		stream->blending_linearity = *update->blending_linearity;
+
 	if (update->drr_trigger_mode) {
 		stream->drr_trigger_mode = *update->drr_trigger_mode;
 	}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 11411fa94665..8878652434d2 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -41,6 +41,7 @@
 #include "dcn10/dcn10_hubbub.h"
 #include "dce/dmub_hw_lock_mgr.h"
 #include "link_service.h"
+#include "custom_float.h"
 
 #define MAX_NUM_MCACHE 8
 
@@ -729,6 +730,386 @@ void get_fams2_visual_confirm_color(
 	}
 }
 
+static bool get_update_dchubp_dpp_flags_status(struct pipe_ctx *pipe)
+{
+	if (!pipe->plane_state) {
+		return false;
+	}
+
+	if ((pipe->update_flags.raw ||
+		dc_pipe_update_bits_is_any_set(&pipe->plane_state->update_bits) ||
+		pipe->stream->update_flags.raw)) {
+		return true;
+	}
+
+	return false;
+}
+
+// Function to check if any update flags are set
+static bool get_pipe_update_bits_status(struct pipe_ctx *pipe, struct dc_plane_state *plane, struct dc_stream_state *stream)
+{
+	(void)stream;
+	if (plane) {
+		return (pipe->update_flags.bits.enable ||
+			pipe->update_flags.bits.plane_changed ||
+			pipe->update_flags.bits.opp_changed ||
+			plane->update_bits.pixel_format_change ||
+			plane->update_bits.horizontal_mirror_change ||
+			plane->update_bits.rotation_change ||
+			plane->update_bits.swizzle_change ||
+			plane->update_bits.dcc_change ||
+			plane->update_bits.bpp_change ||
+			plane->update_bits.scaling_change ||
+			plane->update_bits.plane_size_change);
+	}
+	return false;
+}
+
+void hwss_build_full_sequence(struct dc *dc,
+	struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE],
+	unsigned int *num_steps,
+	struct dc_state *context, bool program_phantom_pipe)
+{
+	(void)program_phantom_pipe;
+	struct dc_plane_state *plane = NULL;
+	struct dc_stream_state *stream = NULL;
+	struct pipe_ctx *current_pipe = NULL;
+	struct pipe_ctx *pipe = NULL;
+	struct dce_hwseq *hws = dc->hwseq;
+	unsigned int i;
+	*num_steps = 0; // Initialize to 0
+	struct block_sequence_state seq_state = { .steps = block_sequence, .num_steps = num_steps };
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++)
+		dc->hwss.detect_pipe_changes(dc->current_state, context, &dc->current_state->res_ctx.pipe_ctx[i],
+			&context->res_ctx.pipe_ctx[i]);
+
+	/* Program triplebuffer if enabled */
+	if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
+		for (i = 0; i < dc->res_pool->pipe_count; i++) {
+			pipe = &context->res_ctx.pipe_ctx[i];
+
+			if (pipe->plane_state) {
+				/* Turn off triple buffer for full update */
+				hwss_add_hubp_program_triplebuffer(&seq_state, dc, pipe, pipe->plane_state->triplebuffer_flips);
+			}
+		}
+	}
+
+	/* Count hubp usage and force pstate change if needed */
+	unsigned int prev_hubp_count = 0;
+	unsigned int hubp_count = 0;
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		if (dc->current_state->res_ctx.pipe_ctx[i].plane_state)
+			prev_hubp_count++;
+		if (context->res_ctx.pipe_ctx[i].plane_state)
+			hubp_count++;
+	}
+
+	if (prev_hubp_count == 0 && hubp_count > 0) {
+		if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
+			hwss_add_hubbub_force_pstate_change_control(&seq_state, dc->res_pool->hubbub, true, false);
+	}
+
+	/* When disabling phantom pipes, turn on phantom OTG first */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		struct dc_stream_state *pipe_stream = dc->current_state->res_ctx.pipe_ctx[i].stream;
+
+		pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+		if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable && pipe_stream &&
+			dc_state_get_pipe_subvp_type(dc->current_state, pipe) == SUBVP_PHANTOM) {
+			struct timing_generator *tg = dc->current_state->res_ctx.pipe_ctx[i].stream_res.tg;
+
+			if (tg->funcs->enable_crtc) {
+				if (dc->hwseq->funcs.blank_pixel_data_sequence)
+					dc->hwseq->funcs.blank_pixel_data_sequence(dc, pipe, true, &seq_state);
+				hwss_add_tg_enable_crtc(&seq_state, tg);
+			}
+		}
+	}
+
+	/* OTG blank before disabling all front ends */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
+				&& !context->res_ctx.pipe_ctx[i].top_pipe
+				&& !context->res_ctx.pipe_ctx[i].prev_odm_pipe
+				&& context->res_ctx.pipe_ctx[i].stream) {
+
+			if (dc->hwseq->funcs.blank_pixel_data_sequence) {
+				dc->hwseq->funcs.blank_pixel_data_sequence(dc, &context->res_ctx.pipe_ctx[i],
+					true, &seq_state);
+			}
+		}
+	}
+
+	/* Disconnect mpcc for pipes being disabled or with opp changes */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable
+			|| context->res_ctx.pipe_ctx[i].update_flags.bits.opp_changed) {
+			struct hubbub *hubbub = dc->res_pool->hubbub;
+
+			/* Phantom pipe DET should be 0, but if a pipe in use is being transitioned to phantom
+			 * then we want to do the programming here (effectively it's being disabled). If we do
+			 * the programming later the DET won't be updated until the OTG for the phantom pipe is
+			 * turned on (i.e. in an MCLK switch) which can come in too late and cause issues with
+			 * DET allocation.
+			 */
+			if ((context->res_ctx.pipe_ctx[i].update_flags.bits.disable ||
+					(context->res_ctx.pipe_ctx[i].plane_state &&
+					dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) ==
+					SUBVP_PHANTOM))) {
+
+				if (hubbub->funcs->program_det_size) {
+					hwss_add_hubp_program_det_size(&seq_state, hubbub,
+						dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
+				}
+
+				if (dc->res_pool->hubbub->funcs->program_det_segments) {
+					hwss_add_hubp_program_det_segments(&seq_state, hubbub,
+						dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
+				}
+			}
+
+			if (hws->funcs.plane_atomic_disconnect_sequence)
+				hws->funcs.plane_atomic_disconnect_sequence(dc, dc->current_state,
+					&dc->current_state->res_ctx.pipe_ctx[i], &seq_state);
+		}
+	}
+
+	/* update ODM for blanked OTG master pipes */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		pipe = &context->res_ctx.pipe_ctx[i];
+		if (resource_is_pipe_type(pipe, OTG_MASTER) &&
+				!resource_is_pipe_type(pipe, DPP_PIPE) &&
+				pipe->update_flags.bits.odm) {
+			if (hws->funcs.update_odm_sequence)
+				hws->funcs.update_odm_sequence(dc, context, pipe, &seq_state);
+		}
+	}
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		pipe = &context->res_ctx.pipe_ctx[i];
+		if (pipe->update_flags.bits.disable) {
+			struct cm_hist_control hist_disable = { .channels_enabled = 0 };
+
+			hwss_add_dpp_program_cm_hist(&seq_state, pipe->plane_res.dpp,
+				hist_disable, COLOR_SPACE_UNKNOWN);
+		}
+	}
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		pipe = &context->res_ctx.pipe_ctx[i];
+
+		if (pipe->plane_state && !pipe->top_pipe) {
+			while (pipe) {
+				if (pipe->stream &&
+						dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
+					if (hws->funcs.program_pipe_sequence)
+						hws->funcs.program_pipe_sequence(dc, pipe, context, &seq_state);
+				}
+
+				pipe = pipe->bottom_pipe;
+			}
+		}
+
+		/* Program secondary blending tree and writeback pipes */
+		pipe = &context->res_ctx.pipe_ctx[i];
+		if (!pipe->top_pipe && !pipe->prev_odm_pipe
+			&& pipe->stream && pipe->stream->num_wb_info > 0
+			&& (pipe->update_flags.raw || (pipe->plane_state && dc_pipe_update_bits_is_any_set(&pipe->plane_state->update_bits))
+				|| pipe->stream->update_flags.raw)) {
+
+			if (hws->funcs.program_all_writeback_pipes_in_tree_sequence)
+				hws->funcs.program_all_writeback_pipes_in_tree_sequence(dc, pipe->stream,
+					context, &seq_state);
+		}
+
+		/* Avoid underflow by check of pipe line read when adding 2nd plane. */
+		if (hws->wa.wait_hubpret_read_start_during_mpo_transition &&
+				!pipe->top_pipe &&
+				pipe->stream &&
+				pipe->plane_res.hubp->funcs->hubp_wait_pipe_read_start &&
+				dc->current_state->stream_status[0].plane_count == 1 &&
+				context->stream_status[0].plane_count > 1) {
+			hwss_add_hubp_wait_pipe_read_start(&seq_state, pipe->plane_res.hubp);
+		}
+	}
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		current_pipe = &context->res_ctx.pipe_ctx[i];
+
+		while (current_pipe) {
+			plane = current_pipe->plane_state;
+			stream = current_pipe->stream;
+			bool is_phantom = (dc_state_get_pipe_subvp_type(context, current_pipe) == SUBVP_PHANTOM);
+
+			if (get_update_dchubp_dpp_flags_status(current_pipe)) {
+				if (!is_phantom && plane && stream) {
+					if (get_pipe_update_bits_status(current_pipe, plane, stream)) {
+						struct plane_size size = plane->plane_size;
+
+						size.surface_size = current_pipe->plane_res.scl_data.viewport;
+						hwss_add_hubp_program_surface_config(&seq_state, current_pipe->plane_res.hubp,
+							plane->format, &plane->tiling_info, size, plane->rotation, &plane->dcc,
+							plane->horizontal_mirror, 0);
+					}
+
+					if (current_pipe->plane_res.hubp->funcs->hubp_program_mcache_id_and_split_coordinate)
+						hwss_add_hubp_program_mcache_id(&seq_state, current_pipe->plane_res.hubp, &current_pipe->mcache_regs);
+
+					if (current_pipe->plane_res.dpp->funcs->dpp_program_upsp) {
+						block_sequence[*num_steps].params.program_upsp_params.pipe_ctx = current_pipe;
+						block_sequence[*num_steps].func = DPP_PROGRAM_UPSP;
+						(*num_steps)++;
+					}
+				}
+			}
+			current_pipe = current_pipe->bottom_pipe;
+		}
+	}
+}
+
+void hwss_build_post_unlock_full_sequence(struct dc *dc,
+	struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE],
+	unsigned int *num_steps,
+	struct dc_state *context)
+{
+	unsigned int i;
+	struct dce_hwseq *hwseq = dc->hwseq;
+	*num_steps = 0; // Initialize to 0
+	struct block_sequence_state seq_state = { .steps = block_sequence, .num_steps = num_steps };
+
+	/* Reset OPP for pipes transitioning from OPP_HEAD to non-OPP_HEAD */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		if (resource_is_pipe_type(&dc->current_state->res_ctx.pipe_ctx[i], OPP_HEAD) &&
+				!resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], OPP_HEAD)) {
+
+			if (dc->hwss.post_unlock_reset_opp_sequence)
+				dc->hwss.post_unlock_reset_opp_sequence(dc, &dc->current_state->res_ctx.pipe_ctx[i],
+					&seq_state);
+		}
+	}
+
+	/* Disable planes that are being disabled */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) {
+			if (dc->hwss.disable_plane_sequence)
+				dc->hwss.disable_plane_sequence(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i],
+					&seq_state);
+		}
+	}
+
+	/* Wait for flip pending on pipes being enabled */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+		if (pipe->plane_state && !pipe->top_pipe && pipe->update_flags.bits.enable &&
+			dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
+
+			unsigned int polling_interval_us;
+				polling_interval_us = 1;
+			hwss_add_hubp_wait_flip_pending(&seq_state, pipe->plane_res.hubp, 100000, polling_interval_us);
+		}
+	}
+
+	/* Wait for double buffer pending when ODM slice count increases */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+		struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+		if (resource_is_pipe_type(old_pipe, OTG_MASTER) && resource_is_pipe_type(pipe, OTG_MASTER) &&
+			resource_get_odm_slice_count(old_pipe) < resource_get_odm_slice_count(pipe) &&
+			dc_state_get_pipe_subvp_type(context, pipe) != SUBVP_PHANTOM) {
+
+			unsigned int polling_interval_us;
+			polling_interval_us = 1;
+			hwss_add_tg_wait_double_buffer_pending(&seq_state, pipe->stream_res.tg, 100000, polling_interval_us);
+		}
+	}
+
+	/* Force pstate change control to false */
+	if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
+		hwss_add_hubbub_force_pstate_change_control(&seq_state, dc->res_pool->hubbub, false, false);
+
+	/* Program phantom pipes */
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+		if (pipe->plane_state && !pipe->top_pipe) {
+			while (pipe) {
+				if (pipe->stream && dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) {
+					/* Apply update flags for phantom pipes using existing HWS functions */
+					if (dc->hwss.apply_update_flags_for_phantom)
+						hwss_add_hws_apply_update_flags_for_phantom(&seq_state, pipe);
+					if (dc->hwss.update_phantom_vp_position)
+						hwss_add_hws_update_phantom_vp_position(&seq_state, dc, context, pipe);
+
+					/* Program the phantom pipe - use program_pipe_sequence if available */
+					if (dc->hwseq && dc->hwseq->funcs.program_pipe_sequence)
+						dc->hwseq->funcs.program_pipe_sequence(dc, pipe, context, &seq_state);
+				}
+				pipe = pipe->bottom_pipe;
+			}
+		}
+	}
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+		while (pipe) {
+			struct dc_plane_state *plane = pipe->plane_state;
+			struct dc_stream_state *stream = pipe->stream;
+			bool is_phantom = (dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM);
+
+			if (get_update_dchubp_dpp_flags_status(pipe)) {
+				if (is_phantom && plane && stream) {
+					if (get_pipe_update_bits_status(pipe, plane, stream)) {
+						struct plane_size size = plane->plane_size;
+
+						size.surface_size = pipe->plane_res.scl_data.viewport;
+						hwss_add_hubp_program_surface_config(&seq_state, pipe->plane_res.hubp,
+							plane->format, &plane->tiling_info, size, plane->rotation, &plane->dcc,
+							plane->horizontal_mirror, 0);
+					}
+
+					if (pipe->plane_res.hubp->funcs->hubp_program_mcache_id_and_split_coordinate)
+						hwss_add_hubp_program_mcache_id(&seq_state, pipe->plane_res.hubp, &pipe->mcache_regs);
+				}
+			}
+			pipe = pipe->bottom_pipe;
+		}
+	}
+
+	/* Update force pstate if hwseq is available */
+	if (hwseq && hwseq->funcs.update_force_pstate)
+		hwss_add_update_force_pstate(&seq_state, dc, context);
+
+	/* Program MALL pipe configuration */
+	if (hwseq && hwseq->funcs.program_mall_pipe_config_sequence)
+		hwseq->funcs.program_mall_pipe_config_sequence(dc, context, &seq_state);
+
+	/* Apply DEDCN21 147 WA if needed */
+	if (hwseq && hwseq->wa.DEGVIDCN21)
+		hwss_add_hubbub_apply_dedcn21_147_wa(&seq_state, dc->res_pool->hubbub);
+
+	/* Handle stutter underflow WA during MPO transitions */
+	if (hwseq && hwseq->wa.disallow_self_refresh_during_multi_plane_transition &&
+			dc->current_state->stream_status[0].plane_count == 1 &&
+			context->stream_status[0].plane_count > 1) {
+
+		hwss_add_hubbub_allow_self_refresh_control(&seq_state, dc->res_pool->hubbub, false,
+			&hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied);
+
+		/* Get frame count for WA state tracking - this needs to be done immediately after the above call */
+		if (dc->res_pool->timing_generators[0]->funcs->get_frame_count) {
+			hwss_add_tg_get_frame_count(&seq_state, dc->res_pool->timing_generators[0],
+				&hwseq->wa_state.disallow_self_refresh_during_multi_plane_transition_applied_on_frame);
+		}
+	}
+}
+
 void hwss_build_fast_sequence(struct dc *dc,
 		struct dc_dmub_cmd *dc_dmub_cmd,
 		unsigned int dmub_cmd_count,
@@ -1058,6 +1439,16 @@ void hwss_build_fast_sequence(struct dc *dc,
 					(*num_steps)++;
 				}
 
+				if (current_mpc_pipe->plane_state->update_bits.lut_3d &&
+						current_mpc_pipe->plane_state->cm.flags.bits.lut3d_dma_enable &&
+						current_mpc_pipe->plane_state->cm.flags.bits.shaper_enable &&
+						current_mpc_pipe->plane_state->cm.flags.bits.lut3d_enable &&
+						current_mpc_pipe->plane_res.hubp->funcs->hubp_enable_3dlut_fl) {
+					block_sequence[*num_steps].params.hubp_enable_3dlut_fl_params.hubp =
+						current_mpc_pipe->plane_res.hubp;
+					block_sequence[*num_steps].func = HUBP_ENABLE_3DLUT_FL;
+					(*num_steps)++;
+				}
 				if (hws->funcs.set_input_transfer_func && current_mpc_pipe->plane_state->update_bits.gamma_change) {
 					block_sequence[*num_steps].params.set_input_transfer_func_params.dc = dc;
 					block_sequence[*num_steps].params.set_input_transfer_func_params.pipe_ctx = current_mpc_pipe;
@@ -1279,6 +1670,9 @@ void hwss_execute_sequence(struct dc *dc,
 		case DPP_SET_OUTPUT_TRANSFER_FUNC:
 			hws->funcs.set_output_transfer_func(&params->set_output_transfer_func_params);
 			break;
+		case DPP_PROGRAM_UPSP:
+			hwss_program_upsp(params);
+			break;
 		case MPC_UPDATE_VISUAL_CONFIRM:
 			dc->hwss.update_visual_confirm_color(params->update_visual_confirm_params.dc,
 					params->update_visual_confirm_params.pipe_ctx,
@@ -2448,6 +2842,22 @@ void hwss_program_bias_and_scale(union block_sequence_params *params)
 		dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
 }
 
+void hwss_program_upsp(union block_sequence_params *params)
+{
+	struct pipe_ctx *pipe_ctx = params->program_upsp_params.pipe_ctx;
+	struct dpp *dpp = pipe_ctx->plane_res.dpp;
+	struct dscl_prog_data *dscl_prog_data = &pipe_ctx->plane_res.scl_data.dscl_prog_data;
+
+	if (!dpp || !dscl_prog_data)
+		return;
+
+	if (dpp && dpp->funcs->dpp_program_upsp) {
+		// program upsampler
+		dpp->funcs->dpp_program_upsp(dpp,
+				dscl_prog_data);
+	}
+}
+
 void hwss_power_on_mpc_mem_pwr(union block_sequence_params *params)
 {
 	struct mpc *mpc = params->power_on_mpc_mem_pwr_params.mpc;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index b970f152d67f..7eaaf38cd9ab 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -80,6 +80,7 @@
 #include "dcn401/dcn401_resource.h"
 #include "dcn42/dcn42_resource.h"
 #include "dcn42b/dcn42b_resource.h"
+#include "dcn60/dcn60_resource.h"
 #if defined(CONFIG_DRM_AMD_DC_FP)
 #include "dc_spl_translate.h"
 #endif
@@ -261,6 +262,9 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
 	case AMDGPU_FAMILY_GC_11_5_4:
 			dc_version = DCN_VERSION_4_2;
 	break;
+	case AMDGPU_FAMILY_GC_13_0_1:
+			dc_version = DCN_VERSION_6_0;
+		break;
 	default:
 		dc_version = DCE_VERSION_UNKNOWN;
 		break;
@@ -383,6 +387,9 @@ struct resource_pool *dc_create_resource_pool(struct dc  *dc,
 	case DCN_VERSION_4_2B:
 		res_pool = dcn42b_create_resource_pool(init_data, dc);
 		break;
+	case DCN_VERSION_6_0:
+		res_pool = dcn60_create_resource_pool(init_data, dc);
+		break;
 #endif /* CONFIG_DRM_AMD_DC_FP */
 	default:
 		break;
@@ -818,6 +825,36 @@ static enum dc_pixel_format convert_pixel_format_to_dalsurface(
 	case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
 		dal_pixel_format = PIXEL_FORMAT_420BPP10;
 		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P208:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P208:
+		dal_pixel_format = PIXEL_FORMAT_422BPP8;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P210:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P210:
+		dal_pixel_format = PIXEL_FORMAT_422BPP10;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P212:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P212:
+		dal_pixel_format = PIXEL_FORMAT_422BPP12;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCrYCb:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCbYCr:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrYCbY:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbYCrY:
+		dal_pixel_format = PIXEL_FORMAT_422BPP8;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCrYCb:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCbYCr:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CrYCbY:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CbYCrY:
+		dal_pixel_format = PIXEL_FORMAT_422BPP10;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCrYCb:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCbYCr:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CrYCbY:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CbYCrY:
+		dal_pixel_format = PIXEL_FORMAT_422BPP12;
+		break;
 	case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
 	case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
 	default:
@@ -1516,6 +1553,15 @@ void resource_build_test_pattern_params(struct resource_context *res_ctx,
 	}
 }
 
+enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format)
+{
+	if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN && format <= SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb) //420 Formats
+		return UPSP_HORIZONTAL_VERTICAL_UPSAMPLING;
+	if (format > SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb && format < SURFACE_PIXEL_FORMAT_SUBSAMPLE_END) //422 Formats
+		return UPSP_HORIZONTAL_UPSAMPLING_ONLY;
+	return UPSP_BYPASS;
+}
+
 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
 {
 	const struct dc_plane_state *plane_state = pipe_ctx->plane_state;
@@ -1561,6 +1607,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
 			pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP;
 
 		pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha;
+		pipe_ctx->plane_res.scl_data.upsp = resource_is_upsp_required(plane_state->format);
 
 		// Convert pipe_ctx to respective input params for SPL
 		translate_SPL_in_params_from_pipe_ctx(pipe_ctx, spl_in);
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
index b534b1a641af..666212cac105 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
@@ -1155,3 +1155,15 @@ bool dc_state_is_subvp_in_use(struct dc_state *state)
 
 	return false;
 }
+bool dc_state_is_alt_in_use(const struct dc *dc, const struct dc_state *state)
+{
+	uint32_t i;
+	const struct pipe_ctx *pipe;
+
+	for (i = 0; i < dc->res_pool->pipe_count; i++) {
+		pipe = &state->res_ctx.pipe_ctx[i];
+		if (pipe->p_state_type == P_STATE_ALT)
+			return true;
+	}
+	return false;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index cdcf140bc1bb..ce5b9e82db8d 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -405,6 +405,7 @@ bool dc_stream_program_cursor_attributes(
 {
 	struct dc  *dc;
 	bool reset_idle_optimizations = false;
+	bool should_release_dmub_hw_control_lock = false;
 
 	if (!stream)
 		return false;
@@ -413,6 +414,13 @@ bool dc_stream_program_cursor_attributes(
 
 	if (dc_stream_set_cursor_attributes(stream, attributes)) {
 		dc_z10_restore(dc);
+		if (dc->hwss.dmub_hw_control_lock) {
+			if (dc_state_is_alt_in_use(dc, dc->current_state) &&
+			    !dc_dmub_srv_is_cursor_offload_enabled(dc)) {
+				dc->hwss.dmub_hw_control_lock(dc, dc->current_state, true);
+				should_release_dmub_hw_control_lock = true;
+			}
+		}
 		/* disable idle optimizations while updating cursor */
 		if (dc->idle_optimizations_allowed) {
 			dc_allow_idle_optimizations(dc, false);
@@ -425,6 +433,10 @@ bool dc_stream_program_cursor_attributes(
 		if (reset_idle_optimizations && !dc->debug.disable_dmub_reallow_idle)
 			dc_allow_idle_optimizations(dc, true);
 
+		if (dc->hwss.dmub_hw_control_lock) {
+			if (should_release_dmub_hw_control_lock)
+				dc->hwss.dmub_hw_control_lock(dc, dc->current_state, false);
+		}
 		return true;
 	}
 
@@ -507,6 +519,7 @@ bool dc_stream_program_cursor_position(
 	struct dc *dc;
 	bool reset_idle_optimizations = false;
 	const struct dc_cursor_position *old_position;
+	bool should_release_dmub_hw_control_lock = false;
 
 	if (!stream)
 		return false;
@@ -517,6 +530,13 @@ bool dc_stream_program_cursor_position(
 	if (dc_stream_set_cursor_position(stream, position)) {
 		dc_z10_restore(dc);
 
+		if (dc->hwss.dmub_hw_control_lock) {
+			if (dc_state_is_alt_in_use(dc, dc->current_state) &&
+			    !dc_dmub_srv_is_cursor_offload_enabled(dc)) {
+				dc->hwss.dmub_hw_control_lock(dc, dc->current_state, true);
+				should_release_dmub_hw_control_lock = true;
+			}
+		}
 		/* disable idle optimizations if enabling cursor */
 		if (dc->idle_optimizations_allowed &&
 		    (!old_position->enable || dc->debug.exit_idle_opt_for_cursor_updates) &&
@@ -567,6 +587,10 @@ bool dc_stream_program_cursor_position(
 			}
 		}
 
+		if (dc->hwss.dmub_hw_control_lock) {
+			if (should_release_dmub_hw_control_lock)
+				dc->hwss.dmub_hw_control_lock(dc, dc->current_state, false);
+		}
 		return true;
 	}
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 63c0dec85697..cc029af0cef2 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -174,6 +174,13 @@ struct dc_plane_cap {
 		uint32_t fp16 : 1;
 		uint32_t p010 : 1;
 		uint32_t ayuv : 1;
+		uint32_t yuy2 : 1; // Packed 422 8bpc
+		uint32_t y210 : 1; // Packed 422 10bpc
+		uint32_t y212 : 1; // Packed 422 12bpc
+		uint32_t p208 : 1; // Planar 422 8bpc
+		uint32_t p210 : 1; // Planar 422 10bpc
+		uint32_t p212 : 1; // Planar 422 12bpc
+		/* Not all caps will be used/supported */
 	} pixel_format_support;
 	// max upscaling factor x1000
 	// upscaling factors are always >= 1
@@ -240,6 +247,7 @@ struct rom_curve_caps {
  * @ogam_ram: programmable out/blend gamma LUT
  * @ocsc: output color space conversion
  * @dgam_rom_for_yuv: pre-defined degamma LUT for YUV planes
+ * @upsp_pre_scaler: Ability to upsample 420/422 before scaling
  * @dgam_rom_caps: pre-definied curve caps for degamma 1D LUT
  * @ogam_rom_caps: pre-definied curve caps for regamma 1D LUT
  *
@@ -256,6 +264,7 @@ struct dpp_color_caps {
 	uint16_t ogam_ram : 1;
 	uint16_t ocsc : 1;
 	uint16_t dgam_rom_for_yuv : 1;
+	uint16_t upsp_pre_scaler : 1;
 	struct rom_curve_caps dgam_rom_caps;
 	struct rom_curve_caps ogam_rom_caps;
 };
@@ -617,6 +626,7 @@ struct dc_config {
 	bool unify_link_enc_assignment;
 	bool enable_cursor_offload;
 	bool dp_connector_no_native_i2c;
+	unsigned int link_index_with_no_ddc;
 	bool frame_update_cmd_version2;
 	struct spl_sharpness_range dcn_sharpness_range;
 	struct spl_sharpness_range dcn_override_sharpness_range;
@@ -785,6 +795,7 @@ struct dc_clocks {
 	 */
 	bool fw_based_mclk_switching;
 	bool fw_based_mclk_switching_shut_down;
+	bool alt_ch_pstate_switch;
 	int prev_num_ways;
 	enum dtm_pstate dtm_level;
 	int max_supported_dppclk_khz;
@@ -795,6 +806,18 @@ struct dc_clocks {
 	int idle_fclk_khz;
 	int subvp_prefetch_dramclk_khz;
 	int subvp_prefetch_fclk_khz;
+	/* deprecated: use _KBps variants — will be removed after DML update */
+	unsigned int utm_urgent_bandwidth_lb_Kbps;
+	unsigned int utm_nominal_bandwidth_lb_Kbps;
+	unsigned int utm_urgent_bandwidth_lb_KBps;
+	unsigned int utm_nominal_bandwidth_lb_KBps;
+	unsigned int utm_latency_ub_index;
+	unsigned int utm_lsdma_bandwidth_lb_KBps;
+	unsigned int utm_nominal_max_latency_ub_ns;
+	unsigned int utm_nominal_avg_latency_ub_ns;
+	/* deprecated: use _KBps variant — will be removed after DML update */
+	unsigned int required_avg_active_bandwidth_Kbps;
+	unsigned int required_avg_active_bandwidth_KBps;
 
 	/* Stutter efficiency is technically not clock values
 	 * but stored here so the values are part of the update_clocks call similar to num_ways
@@ -1739,7 +1762,7 @@ struct dc_plane_state {
 	bool adaptive_sharpness_en;
 	int adaptive_sharpness_policy;
 	unsigned int sharpness_level;
-	enum linear_light_scaling linear_light_scaling;
+	enum dc_scaling_linearity scaling_linearity;
 	unsigned int sdr_white_level_nits;
 	struct cm_hist_control cm_hist_control;
 	struct spl_sharpness_range sharpness_range;
@@ -1763,6 +1786,7 @@ struct dc_plane_info {
 	bool input_csc_enabled;
 	unsigned int layer_index;
 	enum chroma_cositing cositing;
+	enum dc_scaling_linearity scaling_linearity;
 };
 
 #include "dc_stream.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
index 80a21d7cae90..47fa3d4265e0 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -2431,3 +2431,47 @@ void dc_dmub_srv_log_preos_dmcub_info(struct dc_dmub_srv *dc_dmub_srv)
 		DC_LOG_DEBUG("fb_offset					: 0x%016llx", dmub->preos_info.fb_offset);
 	}
 }
+
+bool dc_dmub_srv_ihc_set_dig_hdcp_interrupt_dest(
+	struct dc_dmub_srv *dc_dmub_srv,
+	uint8_t dig_id,
+	bool to_dmu)
+{
+	union dmub_rb_cmd cmd;
+
+	if (!dc_dmub_srv || !dc_dmub_srv->dmub)
+		return false;
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	cmd.ihc.header.type = DMUB_CMD__IHC;
+	cmd.ihc.header.sub_type = DMUB_CMD__IHC_SET_DIG_HDCP_INTERRUPT_DEST;
+	cmd.ihc.header.payload_bytes = sizeof(cmd.ihc.data);
+
+	cmd.ihc.data.dig_id = dig_id;
+	cmd.ihc.data.to_dmu = to_dmu ? 1 : 0;
+
+	dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+
+	return true;
+}
+
+void dc_dmub_srv_get_fams2_debug_meta(struct dc_dmub_srv *dc_dmub_srv)
+{
+	union dmub_rb_cmd cmd;
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	cmd.ib_fams2_debug_meta.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH;
+	cmd.ib_fams2_debug_meta.header.sub_type = DMUB_CMD__FAMS2_IB_DEBUG_META;
+
+	cmd.ib_fams2_debug_meta.ib_data.src.quad_part = dc_dmub_srv->dmub->ib_mem_gart.gpu_addr;
+	cmd.ib_fams2_debug_meta.ib_data.size = dc_dmub_srv->dmub->ib_mem_gart.size > 0xFFFF ?
+			0xFFFF : (uint16_t)dc_dmub_srv->dmub->ib_mem_gart.size;
+
+	/* flush any existing writes to the buffer to prevent conflicts */
+	dmub_srv_flush_buffer_mem(dc_dmub_srv->dmub, &dc_dmub_srv->dmub->ib_mem_gart);
+
+	dm_execute_dmub_cmd_list(dc_dmub_srv->ctx, 1, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
index 8bdaac0b0f98..6d15ed77c17d 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
@@ -401,4 +401,27 @@ void dc_dmub_srv_release_hw(const struct dc *dc);
  * @dc - pointer to DC object
  */
 void dc_dmub_srv_log_preos_dmcub_info(struct dc_dmub_srv *dc_dmub_srv);
+
+/**
+ * dc_dmub_srv_ihc_set_dig_hdcp_interrupt_dest() - Configure IHC interrupt destination.
+ * @dc_dmub_srv: DMUB service handle
+ * @dig_id: DIG engine ID (0-3)
+ * @to_dmu: Route interrupt to DMU (true) or not (false)
+ *
+ * Sends command to DMUB firmware to configure IHC interrupt routing
+ * for HDCP I2C transfer requests.
+ *
+ * Return: true on success, false on failure
+ */
+bool dc_dmub_srv_ihc_set_dig_hdcp_interrupt_dest(
+	struct dc_dmub_srv *dc_dmub_srv,
+	uint8_t dig_id,
+	bool to_dmu);
+
+/**
+ * dc_dmub_srv_get_fams2_debug_meta() - Queries for FAMS2 debug metadata from DMUB and logs it.
+ *
+ * @dc_dmub_srv - pointer to DMUB service object
+ */
+void dc_dmub_srv_get_fams2_debug_meta(struct dc_dmub_srv *dc_dmub_srv);
 #endif /* _DMUB_DC_SRV_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c
index cc7fea613d9e..c1d9c3ef0a4b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c
@@ -530,6 +530,8 @@ char *dce_version_to_string(const int version)
 		return "DCN 4.2";
 	case DCN_VERSION_4_2B:
 		return "DCN 4.2B";
+	case DCN_VERSION_6_0:
+		return "DCN 6.0";
 	default:
 		return "Unknown";
 	}
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index a0272ee92285..aeac5a45e13b 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -205,9 +205,32 @@ enum surface_pixel_format {
 	SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb,
 	SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr,
 	SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb,
+	/* Planar 422 Formats*/
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P208, // 8 bpc
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P208, // 8 bpc
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P210, // 10 bpc
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P210, // 10 bpc
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P212, // 12 bpc
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P212, // 12 bpc
 	SURFACE_PIXEL_FORMAT_SUBSAMPLE_END,
 	SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010 =
 		SURFACE_PIXEL_FORMAT_SUBSAMPLE_END,
+	/* packed 422 formats, they should reside here as the necessity for programming chroma parameters are determined wrt SURFACE_PIXEL_FORMAT_SUBSAMPLE_END*/
+	/* Packed 422 Format, 8bpc*/
+	SURFACE_PIXEL_FORMAT_VIDEO_422_YCrYCb,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_YCbYCr,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CrYCbY,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_CbYCrY,
+	/* Packed 422 Format, 10bpc*/
+	SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCrYCb,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCbYCr,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CrYCbY,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CbYCrY,
+	/* Packed 422 Format, 12bpc*/
+	SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCrYCb,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCbYCr,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CrYCbY,
+	SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CbYCrY,
 	SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102,
 	SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888,
 	SURFACE_PIXEL_FORMAT_INVALID
@@ -230,13 +253,19 @@ enum dc_pixel_format {
 	/*video*/
 	PIXEL_FORMAT_420BPP8,
 	PIXEL_FORMAT_420BPP10,
+	// Align with SPL formats
+	PIXEL_FORMAT_422BPP8,
+	PIXEL_FORMAT_422BPP10,
+	PIXEL_FORMAT_422BPP12,
+	PIXEL_FORMAT_444BPP8,
+	PIXEL_FORMAT_444BPP10,
 	/*end of pixel format definition*/
 	PIXEL_FORMAT_INVALID,
 
 	PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8,
 	PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16,
 	PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP8,
-	PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP10,
+	PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_444BPP10,
 	PIXEL_FORMAT_UNKNOWN
 };
 
@@ -651,6 +680,7 @@ struct dc_cursor_attributes {
 	enum dc_rotation_angle rotation_angle;
 
 	union dc_cursor_attribute_flags attribute_flags;
+	bool force_cursor_to_disp_pref;
 };
 
 struct dpp_cursor_attributes {
@@ -1249,5 +1279,26 @@ struct cm_hist {
 	uint32_t ch2[256];
 	uint32_t ch3[256];
 };
+
+enum pregam_mode {
+	PREGAM_BYPASS = 0,
+	PREGAM_DEGAM,
+	PREGAM_REGAM
+};
+
+enum degam_lut {
+	DEGAM_SRGB = 0,
+	DEGAM_GAMMA_22,
+	DEGAM_GAMMA_24,
+	DEGAM_GAMMA_26,
+	DEGAM_BT2020,
+	DEGAM_BT2100PQ,
+	DEGAM_BT2100HLG
+};
+
+enum regam_lut {
+	REGAM_20 = 0,
+	REGAM_24
+};
 #endif /* DC_HW_TYPES_H */
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
index bc55f10fba7c..76c0d62031b6 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
@@ -16,6 +16,9 @@ static struct spl_callbacks dcn32_spl_callbacks = {
 static struct spl_callbacks dcn401_spl_callbacks = {
 	.spl_calc_lb_num_partitions = dscl401_spl_calc_lb_num_partitions,
 };
+static struct spl_callbacks dcn50_spl_callbacks = {
+	.spl_calc_lb_num_partitions = dscl401_spl_calc_lb_num_partitions,
+};
 static void populate_splrect_from_rect(struct spl_rect *spl_rect, const struct rect *rect)
 {
 	spl_rect->x = rect->x;
@@ -71,6 +74,23 @@ static void populate_splformat_from_format(enum spl_pixel_format *spl_pixel_form
 	else
 		*spl_pixel_format = SPL_PIXEL_FORMAT_INVALID;
 }
+static void set_linear_light_scaling_preference(const struct dc_plane_state *plane_state, struct spl_in *spl_in)
+{
+	if (plane_state != NULL) {
+		switch (plane_state->scaling_linearity) {
+		case DC_SCALING_LINEARITY_LINEAR:
+			spl_in->lls_pref = LLS_PREF_YES;
+			break;
+		case DC_SCALING_LINEARITY_SOURCE:
+			spl_in->lls_pref = LLS_PREF_NO;
+			break;
+		default:
+			spl_in->lls_pref = LLS_PREF_DONT_CARE;
+			break;
+		}
+	} else
+		spl_in->lls_pref = LLS_PREF_DONT_CARE;
+}
 /// @brief Translate SPL input parameters from pipe context
 /// @param pipe_ctx
 /// @param spl_in
@@ -94,6 +114,9 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl
 	case DCN_VERSION_4_2B:
 		spl_in->callbacks = dcn401_spl_callbacks;
 		break;
+	case DCN_VERSION_6_0:
+		spl_in->callbacks = dcn50_spl_callbacks;
+		break;
 	default:
 		spl_in->callbacks = dcn2_spl_callbacks;
 	}
@@ -189,7 +212,14 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl
 	if (pipe_ctx->stream->ctx->dc->debug.force_lls > 0)
 		spl_in->lls_pref = pipe_ctx->stream->ctx->dc->debug.force_lls;
 	else
-		spl_in->lls_pref = plane_state->linear_light_scaling;
+		if ((plane_state->ctx->dce_version == DCN_VERSION_4_01) ||
+			(plane_state->ctx->dce_version == DCN_VERSION_4_2) ||
+			(plane_state->ctx->dce_version == DCN_VERSION_4_2B))
+			spl_in->lls_pref = LLS_PREF_DONT_CARE;
+		else
+			set_linear_light_scaling_preference(plane_state, spl_in);
+	/* Translate upsampling mode*/
+	spl_in->upsp_mode = pipe_ctx->plane_res.scl_data.upsp;
 	/* Translate chroma subsampling offset ( cositing ) */
 	if (pipe_ctx->stream->ctx->dc->debug.force_cositing)
 		spl_in->basic_in.cositing = pipe_ctx->stream->ctx->dc->debug.force_cositing - 1;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_state_priv.h b/drivers/gpu/drm/amd/display/dc/dc_state_priv.h
index 1d9bae56ff6a..191bb431991f 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_state_priv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_state_priv.h
@@ -125,4 +125,5 @@ bool dc_state_can_clear_stream_cursor_subvp_limit(const struct dc_stream_state *
 
 bool dc_state_is_subvp_in_use(struct dc_state *state);
 
+bool dc_state_is_alt_in_use(const struct dc *dc, const struct dc_state *state);
 #endif /* _DC_STATE_PRIV_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index 4530f294f1c2..934ae381e730 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -329,6 +329,9 @@ struct dc_stream_state {
 
 	enum dc_drr_trigger_mode drr_trigger_mode;
 
+
+	enum dc_blending_linearity blending_linearity;
+	struct dc_update_scratch_space *update_scratch;
 	bool firmware_controlled_hdr_info_packet;
 };
 
@@ -380,6 +383,8 @@ struct dc_stream_update {
 	bool *scaler_sharpener_update;
 	bool *sharpening_required;
 
+	enum dc_blending_linearity *blending_linearity;
+
 	enum dc_drr_trigger_mode *drr_trigger_mode;
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index 3edeb94fba23..b14d882e08d4 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -389,6 +389,16 @@ struct dc_csc_adjustments {
 	struct fixed31_32 hue;
 };
 
+enum dc_scaling_linearity {
+	DC_SCALING_LINEARITY_LINEAR,
+	DC_SCALING_LINEARITY_SOURCE,
+};
+
+enum dc_blending_linearity {
+	DC_BLENDING_LINEARITY_LINEAR,
+	DC_BLENDING_LINEARITY_SOURCE,
+};
+
 /* Scaling format */
 enum scaling_transformation {
 	SCALING_TRANSFORMATION_UNINITIALIZED,
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h
index 088cf305a772..cecfb0a68030 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h
@@ -377,6 +377,13 @@
 	type OTG3_DROP_PIXEL;\
 	type RESYNC_FIFO_LEVEL_ADJUST_EN;
 
+#define DCCG60_REG_FIELD_LIST(type) \
+	type OTG_ADD_DROP_PIXEL_DONE;\
+	type DSCCLK0_SRC_SEL;\
+	type DSCCLK1_SRC_SEL;\
+	type DSCCLK2_SRC_SEL;\
+	type DSCCLK3_SRC_SEL;
+
 struct dccg_shift {
 	DCCG_REG_FIELD_LIST(uint8_t)
 	DCCG3_REG_FIELD_LIST(uint8_t)
@@ -386,6 +393,7 @@ struct dccg_shift {
 	DCCG35_REG_FIELD_LIST(uint8_t)
 	DCCG401_REG_FIELD_LIST(uint8_t)
 	DCCG42_REG_FIELD_LIST(uint8_t)
+	DCCG60_REG_FIELD_LIST(uint8_t)
 };
 
 struct dccg_mask {
@@ -397,6 +405,7 @@ struct dccg_mask {
 	DCCG35_REG_FIELD_LIST(uint32_t)
 	DCCG401_REG_FIELD_LIST(uint32_t)
 	DCCG42_REG_FIELD_LIST(uint32_t)
+	DCCG60_REG_FIELD_LIST(uint32_t)
 };
 
 #define DCCG_REG_VARIABLE_LIST \
@@ -511,6 +520,7 @@ struct dccg_mask {
 struct dccg_registers {
 	DCCG_REG_VARIABLE_LIST;
 	uint32_t OTG_ADD_DROP_PIXEL_CNTL;
+	uint32_t DSCCLK_SRC_SEL;
 };
 
 struct dcn_dccg {
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index ecb8493ec523..e52fb7248a88 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -1496,6 +1496,13 @@ static const struct clock_source_funcs dcn401_clk_src_funcs = {
 	.get_dp_dto_frequency_100hz = dcn401_get_dp_dto_frequency_100hz
 };
 
+static const struct clock_source_funcs dcn50_clk_src_funcs = {
+	.cs_power_down = dce110_clock_source_power_down,
+	.program_pix_clk = dcn401_program_pix_clk,
+	.get_pix_clk_dividers = dcn3_get_pix_clk_dividers,
+	.get_dp_dto_frequency_100hz = dcn401_get_dp_dto_frequency_100hz
+};
+
 /*****************************************/
 /* Constructor                           */
 /*****************************************/
@@ -1924,6 +1931,23 @@ bool dcn401_clk_src_construct(
 
 	return ret;
 }
+
+bool dcn50_clk_src_construct(
+	struct dce110_clk_src *clk_src,
+	struct dc_context *ctx,
+	struct dc_bios *bios,
+	enum clock_source_id id,
+	const struct dce110_clk_src_regs *regs,
+	const struct dce110_clk_src_shift *cs_shift,
+	const struct dce110_clk_src_mask *cs_mask)
+{
+	bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask);
+
+	clk_src->base.funcs = &dcn50_clk_src_funcs;
+
+	return ret;
+}
+
 bool dcn301_clk_src_construct(
 	struct dce110_clk_src *clk_src,
 	struct dc_context *ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h
index 55c96b4b7765..6eca94e99d96 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h
@@ -339,6 +339,15 @@ bool dcn401_clk_src_construct(
 	const struct dce110_clk_src_regs *regs,
 	const struct dce110_clk_src_shift *cs_shift,
 	const struct dce110_clk_src_mask *cs_mask);
+bool dcn50_clk_src_construct(
+	struct dce110_clk_src *clk_src,
+	struct dc_context *ctx,
+	struct dc_bios *bios,
+	enum clock_source_id id,
+	const struct dce110_clk_src_regs *regs,
+	const struct dce110_clk_src_shift *cs_shift,
+	const struct dce110_clk_src_mask *cs_mask);
+
 /* this table is use to find *1.001 and /1.001 pixel rates from non-precise pixel rate */
 struct pixel_rate_range_table_entry {
 	unsigned int range_min_khz;
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h
index eedbd5d2756e..a99879c58027 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.h
@@ -75,12 +75,14 @@ struct dcn10_link_enc_aux_registers {
 	uint32_t AUX_DPHY_RX_CONTROL0;
 	uint32_t AUX_DPHY_TX_CONTROL;
 	uint32_t AUX_DPHY_RX_CONTROL1;
+	uint32_t DC_GPIO_DDC;
 };
 
 struct dcn10_link_enc_hpd_registers {
 	uint32_t DC_HPD_CONTROL;
 	uint32_t DC_HPD_INT_STATUS;
 	uint32_t DC_HPD_TOGGLE_FILT_CNTL;
+	uint32_t HPD_CTRL;
 };
 
 struct dcn10_link_enc_registers {
@@ -171,6 +173,8 @@ struct dcn10_link_enc_registers {
 	uint32_t DIO_LINKF_CNTL;
 	uint32_t DIO_CLK_CNTL;
 	uint32_t DIG_BE_CLK_CNTL;
+	uint32_t HDCP_I2C_CONTROL_0;
+	uint32_t HDCP_INT_CONTROL;
 };
 
 #define LE_SF(reg_name, field_name, post_fix)\
@@ -508,12 +512,23 @@ struct dcn10_link_enc_registers {
 	type SYMCLKF_G_HDCP_GATE_DIS;\
 	type SYMCLKG_G_HDCP_GATE_DIS
 
+#define DCN60_LINK_ENCODER_REG_FIELD_LIST(type) \
+	type HDCP_I2C_DISABLE;\
+	type HDCP_I2C_DDC_SELECT;\
+	type HDCP_I2C_XFER_REQ_MASK;\
+	type AUX_PAD1_MODE;\
+	type HPD1_Y_POL_INVERT;\
+	type HPD2_Y_POL_INVERT;\
+	type HPD3_Y_POL_INVERT;\
+	type HPD4_Y_POL_INVERT
+
 struct dcn10_link_enc_shift {
 	DCN_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
 	DCN20_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
 	DCN30_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
 	DCN31_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
 	DCN35_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
+	DCN60_LINK_ENCODER_REG_FIELD_LIST(uint8_t);
 };
 
 struct dcn10_link_enc_mask {
@@ -522,6 +537,7 @@ struct dcn10_link_enc_mask {
 	DCN30_LINK_ENCODER_REG_FIELD_LIST(uint32_t);
 	DCN31_LINK_ENCODER_REG_FIELD_LIST(uint32_t);
 	DCN35_LINK_ENCODER_REG_FIELD_LIST(uint32_t);
+	DCN60_LINK_ENCODER_REG_FIELD_LIST(uint32_t);
 };
 
 struct dcn10_link_encoder {
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
index 2aaf06d48771..dad4ef565168 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.c
@@ -384,6 +384,20 @@ enum signal_type dcn401_get_dig_mode(
 	}
 }
 
+void dcn401_setup_ri_pj_check_in_sw_or_hw_mode(
+	struct link_encoder *enc,
+	unsigned char aux_or_ddc_instance,
+	bool enable_sw_mode)
+{
+	struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+
+	REG_UPDATE_2(HDCP_I2C_CONTROL_0,
+			HDCP_I2C_DISABLE, enable_sw_mode,
+			HDCP_I2C_DDC_SELECT, aux_or_ddc_instance);
+
+	REG_UPDATE(HDCP_INT_CONTROL, HDCP_I2C_XFER_REQ_MASK, enable_sw_mode);
+}
+
 static const struct link_encoder_funcs dcn401_link_enc_funcs = {
 	.read_state = link_enc2_read_state,
 	.validate_output_with_stream =
@@ -423,6 +437,7 @@ static const struct link_encoder_funcs dcn401_link_enc_funcs = {
 	.get_txffe = dpcs401_get_txffe,
 	.set_txffe = dpcs401_set_txffe,
 	.set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
+	.setup_ri_pj_check_in_sw_or_hw_mode = dcn401_setup_ri_pj_check_in_sw_or_hw_mode,
 	.get_hpd_state = dcn10_get_hpd_state,
 	.program_hpd_filter = dcn10_program_hpd_filter,
 };
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h
index a40c479fada8..62f8f9098b53 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_link_encoder.h
@@ -104,6 +104,11 @@
 	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)
 
+#define LINK_ENCODER_MASK_SH_LIST_DCN60_ON_DCN401(mask_sh) \
+	LE_SF(DIG0_HDCP_I2C_CONTROL_0, HDCP_I2C_DISABLE, mask_sh),\
+	LE_SF(DIG0_HDCP_I2C_CONTROL_0, HDCP_I2C_DDC_SELECT, mask_sh),\
+	LE_SF(DIG0_HDCP_INT_CONTROL, HDCP_I2C_XFER_REQ_MASK, mask_sh)
+
 void dcn401_link_encoder_construct(
 	struct dcn20_link_encoder *enc20,
 	const struct encoder_init_data *init_data,
@@ -147,4 +152,9 @@ enum signal_type dcn401_get_dig_mode(
 bool dcn401_is_dig_enabled(struct link_encoder *enc);
 
 enum signal_type dcn401_get_dig_mode(struct link_encoder *enc);
+
+void dcn401_setup_ri_pj_check_in_sw_or_hw_mode(
+	struct link_encoder *enc,
+	unsigned char aux_or_ddc_instance,
+	bool enable_sw_mode);
 #endif /* __DC_LINK_ENCODER__DCN401_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
index f5252931ce35..c887fdcba049 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
@@ -203,6 +203,14 @@ void dm_helpers_mccs_vcp_set(
 #define EXPORT_IF_KUNIT(symbol)
 #endif
 
+bool dm_helpers_submit_i2c_over_aux(
+	struct ddc_service *ddc,
+	uint32_t address,
+	uint8_t offset,
+	uint8_t *cmdBuffer,
+	uint32_t len,
+	bool read);
+
 bool dm_helpers_dp_handle_test_pattern_request(
 		struct dc_context *ctx,
 		const struct dc_link *link,
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c
index 47164fa150d9..1b0d55e2d7b0 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c
@@ -40,10 +40,10 @@ static void dml21_populate_pmo_options(struct dml2_pmo_options *pmo_options,
 	pmo_options->force_mandatory_uclk_pstate_support = config->pmo.force_mandatory_uclk_pstate_support;
 }
 
-static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(enum dce_version dcn_version)
+static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(const struct dc *in_dc)
 {
 	enum dml2_project_id project_id;
-	switch (dcn_version) {
+	switch (in_dc->ctx->dce_version) {
 	case DCN_VERSION_4_01:
 		project_id = dml2_project_dcn4x_stage2_auto_drr_svp;
 		break;
@@ -51,6 +51,9 @@ static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(enum dce_versi
 	case DCN_VERSION_4_2B:
 		project_id = dml2_project_dcn42;
 		break;
+	case DCN_VERSION_6_0:
+		project_id = dml2_project_dcn6x_soc_var_a;
+		break;
 	default:
 		project_id = dml2_project_invalid;
 		DC_ERR("unsupported dcn version for DML21!");
@@ -64,7 +67,7 @@ void dml21_populate_dml_init_params(struct dml2_initialize_instance_in_out *dml_
 		const struct dml2_configuration_options *config,
 		const struct dc *in_dc)
 {
-	dml_init->options.project_id = dml21_dcn_revision_to_dml2_project_id(in_dc->ctx->dce_version);
+	dml_init->options.project_id = dml21_dcn_revision_to_dml2_project_id(in_dc);
 
 	if (config->use_native_soc_bb_construction) {
 		in_dc->soc_and_ip_translator->translator_funcs->get_soc_bb(&dml_init->soc_bb, in_dc, config);
@@ -75,6 +78,9 @@ void dml21_populate_dml_init_params(struct dml2_initialize_instance_in_out *dml_
 	}
 
 	dml21_populate_pmo_options(&dml_init->options.pmo_options, in_dc, config);
+
+	if (in_dc->clk_mgr && in_dc->clk_mgr->bw_params)
+		dml_init->overrides.explicit_qos_model = in_dc->clk_mgr->bw_params->utm_qos_model;
 }
 
 static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream)
@@ -528,7 +534,6 @@ static void populate_dml21_surface_config_from_plane_state(
 	switch (plane_state->tiling_info.gfxversion) {
 	case DcGfxVersion7:
 	case DcGfxVersion8:
-		break;
 	case DcGfxVersion9:
 	case DcGfxVersion10:
 	case DcGfxVersion11:
@@ -606,6 +611,36 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm
 	case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
 		plane->pixel_format = dml2_rgbe_alpha;
 		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P208:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P208:
+		plane->pixel_format = dml2_422_planar_8;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P210:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P210:
+		plane->pixel_format = dml2_422_planar_10;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrCb_P212:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbCr_P212:
+		plane->pixel_format = dml2_422_planar_12;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCrYCb:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_YCbYCr:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CrYCbY:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_CbYCrY:
+		plane->pixel_format = dml2_422_packed_8;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCrYCb:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_YCbYCr:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CrYCbY:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_10bpc_CbYCrY:
+		plane->pixel_format = dml2_422_packed_10;
+		break;
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCrYCb:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_YCbYCr:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CrYCbY:
+	case SURFACE_PIXEL_FORMAT_VIDEO_422_12bpc_CbYCrY:
+		plane->pixel_format = dml2_422_packed_12;
+		break;
 	default:
 		plane->pixel_format = dml2_444_32;
 		break;
@@ -640,6 +675,8 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm
 			plane->composition.scaler_info.enabled = true;
 	}
 
+	plane->composition.scaler_info.upsp_enabled = (scaler_data->upsp != UPSP_BYPASS);
+
 	/* always_scale is only used for debug purposes not used in production but has to be
 	 * maintained for certain complainces. */
 	if (plane_state->ctx->dc->debug.always_scale == true) {
@@ -836,6 +873,9 @@ static enum dml2_uclk_pstate_change_strategy dml21_force_pstate_method_to_uclk_s
 	case dml2_force_pstate_method_subvp:
 		val = dml2_uclk_pstate_change_strategy_force_mall_svp;
 		break;
+	case dml2_force_pstate_method_alternate:
+		val = dml2_uclk_pstate_change_strategy_force_alternate;
+		break;
 	case dml2_force_pstate_method_auto:
 	default:
 		val = dml2_uclk_pstate_change_strategy_auto;
@@ -952,6 +992,9 @@ void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state
 	context->bw_ctx.bw.dcn.clk.socclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.socclk_khz;
 	context->bw_ctx.bw.dcn.clk.subvp_prefetch_dramclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.uclk_khz;
 	context->bw_ctx.bw.dcn.clk.subvp_prefetch_fclk_khz = in_ctx->v21.mode_programming.programming->min_clocks.dcn4x.svp_prefetch_no_throttle.fclk_khz;
+	context->bw_ctx.bw.dcn.clk.utm_latency_ub_index = 0; /* TODO - derive from qos model */
+	context->bw_ctx.bw.dcn.clk.utm_nominal_bandwidth_lb_Kbps = (unsigned int) in_ctx->v21.mode_programming.programming->qos_bound.bandwidth_lb.dcn5.non_urgent_bandwidth_kbps;
+	context->bw_ctx.bw.dcn.clk.utm_urgent_bandwidth_lb_Kbps = (unsigned int) in_ctx->v21.mode_programming.programming->qos_bound.bandwidth_lb.dcn5.urgent_bandwidth_kbps;
 	context->bw_ctx.bw.dcn.clk.stutter_efficiency.base_efficiency = (uint8_t)in_ctx->v21.mode_programming.programming->stutter.base_percent_efficiency;
 	context->bw_ctx.bw.dcn.clk.stutter_efficiency.low_power_efficiency = (uint8_t)in_ctx->v21.mode_programming.programming->stutter.low_power_percent_efficiency;
 	context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_efficiency = (uint8_t)in_ctx->v21.mode_programming.programming->informative.power_management.z8.stutter_efficiency;
@@ -1060,6 +1103,9 @@ void dml21_set_dc_p_state_type(
 		else
 			pipe_ctx->p_state_type = P_STATE_FPO;
 		break;
+	case dml2_pstate_method_alternate:
+		pipe_ctx->p_state_type = P_STATE_ALT;
+		break;
 	default:
 		pipe_ctx->p_state_type = P_STATE_UNKNOWN;
 		break;
@@ -1087,6 +1133,9 @@ void dml21_init_min_clocks_for_dc_state(struct dml2_context *in_ctx, struct dc_s
 	min_clocks->subvp_prefetch_dramclk_khz = 0;
 	min_clocks->subvp_prefetch_fclk_khz = 0;
 	min_clocks->phyclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.phyclk.clk_values_khz[lowest_dpm_state_index];
+	min_clocks->utm_latency_ub_index = 0; /* TODO - derive from qos model */
+	min_clocks->utm_nominal_bandwidth_lb_Kbps = 0;
+	min_clocks->utm_urgent_bandwidth_lb_Kbps = 0;
 	min_clocks->stutter_efficiency.base_efficiency = 1;
 	min_clocks->stutter_efficiency.low_power_efficiency = 1;
 	min_clocks->stutter_efficiency.z8_stutter_efficiency = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c
index 012dff4cf3fa..1ade48b8b621 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c
@@ -375,6 +375,130 @@ void dml21_handle_phantom_streams_planes(const struct dc *dc, struct dc_state *c
 		dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, dc->current_state);
 }
 
+static uint32_t calc_svp_size_64kb(uint32_t total_size_bytes)
+{
+	return (total_size_bytes + 0xFFFF) >> 16;
+}
+
+static unsigned int dml21_build_fams2_stream_programming_v3(const struct dc *dc,
+		struct dc_state *context,
+		struct dml2_context *dml_ctx)
+{
+	int dml_stream_idx, dc_stream_idx, dc_plane_idx, svp_idx;
+	unsigned int dc_pipe_idx;
+	unsigned int num_fams2_streams = 0;
+	unsigned int svp_size_64kb[2] = {0};
+	struct pipe_ctx *pipe;
+
+	for (dc_stream_idx = 0; dc_stream_idx < context->stream_count; dc_stream_idx++) {
+		enum fams2_stream_type type = 0;
+
+		union dmub_cmd_fams2_config *static_base_state = &context->bw_ctx.bw.dcn.fams2_stream_base_params[num_fams2_streams];
+		struct dmub_fams2_cmd_alternate_stream_static_state *alternate_static_state;
+
+		struct dc_stream_state *stream = context->streams[dc_stream_idx];
+
+		if (context->stream_status[dc_stream_idx].plane_count == 0 ||
+				dml_ctx->config.svp_pstate.callbacks.get_stream_subvp_type(context, stream) == SUBVP_PHANTOM) {
+			/* can ignore blanked or phantom streams */
+			continue;
+		}
+
+		dml_stream_idx = dml21_helper_find_dml_pipe_idx_by_stream_id(dml_ctx, stream->stream_id);
+		if (dml_stream_idx < 0) {
+			ASSERT(dml_stream_idx >= 0);
+			continue;
+		}
+
+		/* copy static state from PMO */
+		memcpy(static_base_state,
+				&dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_base_params,
+				sizeof(union dmub_cmd_fams2_config));
+
+		memcpy(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2[num_fams2_streams],
+				&dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params_v2,
+				sizeof(union dmub_fams2_stream_static_sub_state_v2));
+
+		type = static_base_state->stream_v1.base.type;
+
+		/* get information from context */
+		ASSERT(context->stream_status[dc_stream_idx].plane_count >= 0 &&
+				context->stream_status[dc_stream_idx].plane_count <= 0xFF);
+		ASSERT(context->stream_status[dc_stream_idx].primary_otg_inst >= 0 &&
+				context->stream_status[dc_stream_idx].primary_otg_inst <= 0xFF);
+		static_base_state->stream_v1.base.num_planes = (uint8_t)context->stream_status[dc_stream_idx].plane_count;
+		static_base_state->stream_v1.base.otg_inst = (uint8_t)context->stream_status[dc_stream_idx].primary_otg_inst;
+
+		/* populate pipe masks for planes */
+		for (dc_plane_idx = 0; dc_plane_idx < context->stream_status[dc_stream_idx].plane_count; dc_plane_idx++) {
+			for (dc_pipe_idx = 0; dc_pipe_idx < dc->res_pool->pipe_count; dc_pipe_idx++) {
+				if (context->res_ctx.pipe_ctx[dc_pipe_idx].stream &&
+						context->res_ctx.pipe_ctx[dc_pipe_idx].stream->stream_id == stream->stream_id &&
+						context->res_ctx.pipe_ctx[dc_pipe_idx].plane_state == context->stream_status[dc_stream_idx].plane_states[dc_plane_idx]) {
+					static_base_state->stream_v1.base.pipe_mask |= (1 << dc_pipe_idx);
+					static_base_state->stream_v1.base.plane_pipe_masks[dc_plane_idx] |= (1 << dc_pipe_idx);
+				}
+			}
+		}
+
+		/* get per method programming */
+		switch (type) {
+		case FAMS2_STREAM_TYPE_VBLANK:
+		case FAMS2_STREAM_TYPE_VACTIVE:
+		case FAMS2_STREAM_TYPE_DRR:
+			break;
+		case FAMS2_STREAM_TYPE_ALTERNATE:
+			alternate_static_state = &context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2[num_fams2_streams].alternate;
+
+			for (dc_plane_idx = 0; dc_plane_idx < context->stream_status[dc_stream_idx].plane_count; dc_plane_idx++) {
+				for (dc_pipe_idx = 0; dc_pipe_idx < dc->res_pool->pipe_count; dc_pipe_idx++) {
+					pipe = &context->res_ctx.pipe_ctx[dc_pipe_idx];
+					if (pipe->plane_state != context->stream_status[dc_stream_idx].plane_states[dc_plane_idx])
+						continue;
+					// TODO: Mapping between plane_idx within stream_res and plane_idx within alternate_stream_static_state
+					// should be matching, but it's better to have an explicit map / check (future improvement)
+					ASSERT(pipe->plane_res.scl_data.viewport.height >= 0 && pipe->plane_res.scl_data.viewport.height <= 0xFFFF);
+					ASSERT(pipe->plane_res.scl_data.viewport.width >= 0 && pipe->plane_res.scl_data.viewport.width <= 0xFFFF);
+					ASSERT(pipe->plane_res.scl_data.viewport.x >= 0 && pipe->plane_res.scl_data.viewport.x <= 0xFFFF);
+					ASSERT(pipe->plane_res.scl_data.viewport.y >= 0 && pipe->plane_res.scl_data.viewport.y <= 0xFFFF);
+					alternate_static_state->pipe_viewports[dc_pipe_idx].luma.height = (uint16_t)pipe->plane_res.scl_data.viewport.height;
+					alternate_static_state->pipe_viewports[dc_pipe_idx].luma.width = (uint16_t)pipe->plane_res.scl_data.viewport.width;
+					alternate_static_state->pipe_viewports[dc_pipe_idx].luma.x = (uint16_t)pipe->plane_res.scl_data.viewport.x;
+					alternate_static_state->pipe_viewports[dc_pipe_idx].luma.y = (uint16_t)pipe->plane_res.scl_data.viewport.y;
+					if (alternate_static_state->config[dc_plane_idx].bits.is_multi_planar) {
+						ASSERT(pipe->plane_res.scl_data.viewport_c.height >= 0 && pipe->plane_res.scl_data.viewport_c.height <= 0xFFFF);
+						ASSERT(pipe->plane_res.scl_data.viewport_c.width >= 0 && pipe->plane_res.scl_data.viewport_c.width <= 0xFFFF);
+						ASSERT(pipe->plane_res.scl_data.viewport_c.x >= 0 && pipe->plane_res.scl_data.viewport_c.x <= 0xFFFF);
+						ASSERT(pipe->plane_res.scl_data.viewport_c.y >= 0 && pipe->plane_res.scl_data.viewport_c.y <= 0xFFFF);
+						alternate_static_state->pipe_viewports[dc_pipe_idx].chroma.height = (uint16_t)pipe->plane_res.scl_data.viewport_c.height;
+						alternate_static_state->pipe_viewports[dc_pipe_idx].chroma.width = (uint16_t)pipe->plane_res.scl_data.viewport_c.width;
+						alternate_static_state->pipe_viewports[dc_pipe_idx].chroma.x = (uint16_t)pipe->plane_res.scl_data.viewport_c.x;
+						alternate_static_state->pipe_viewports[dc_pipe_idx].chroma.y = (uint16_t)pipe->plane_res.scl_data.viewport_c.y;
+					}
+					for (svp_idx = 0; svp_idx < 2; svp_idx++) {
+						alternate_static_state->pipe_copy_addr_47_16[svp_idx][dc_pipe_idx] =
+								dml_ctx->config.alt_ch_cfg.region_base_addr_47_16[svp_idx] + svp_size_64kb[svp_idx];
+						svp_size_64kb[svp_idx] += calc_svp_size_64kb(alternate_static_state->pipe_copy_max_size[svp_idx][dc_plane_idx]);
+						if (alternate_static_state->config[dc_plane_idx].bits.is_multi_planar) {
+							alternate_static_state->pipe_copy_addr_47_16_c[svp_idx][dc_pipe_idx] =
+									dml_ctx->config.alt_ch_cfg.region_base_addr_47_16[svp_idx] + svp_size_64kb[svp_idx];
+							svp_size_64kb[svp_idx] += calc_svp_size_64kb(alternate_static_state->pipe_copy_max_size_c[svp_idx][dc_plane_idx]);
+						}
+					}
+				}
+			}
+			break;
+		case FAMS2_STREAM_TYPE_SUBVP:
+		default:
+			ASSERT(false);
+			break;
+		}
+
+		num_fams2_streams++;
+	}
+
+	return num_fams2_streams;
+}
 
 static unsigned int dml21_build_fams2_stream_programming_v2(const struct dc *dc,
 		struct dc_state *context,
@@ -509,7 +633,9 @@ void dml21_build_fams2_programming(const struct dc *dc,
 
 	if (dml_ctx->v21.mode_programming.programming->fams2_required ||
 			dml_ctx->v21.mode_programming.programming->legacy_pstate_info_for_dmu) {
-		if (dc->debug.fams_version.major == 2) {
+		if (dc->debug.fams_version.major == 3) {
+			num_fams2_streams = dml21_build_fams2_stream_programming_v3(dc, context, dml_ctx);
+		} else if (dc->debug.fams_version.major == 2) {
 			num_fams2_streams = dml21_build_fams2_stream_programming_v2(dc, context, dml_ctx);
 		}
 	}
@@ -525,6 +651,7 @@ void dml21_build_fams2_programming(const struct dc *dc,
 
 	context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching =
 			(context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable != 0);
+	context->bw_ctx.bw.dcn.clk.alt_ch_pstate_switch = dc_state_is_alt_in_use(dc, context);
 }
 
 bool dml21_is_plane1_enabled(enum dml2_source_format_class source_format)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h
index 79dfba54344c..f402bb933f7d 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h
@@ -102,6 +102,7 @@ enum dml2_uclk_pstate_change_strategy {
 	dml2_uclk_pstate_change_strategy_force_drr = 3,
 	dml2_uclk_pstate_change_strategy_force_mall_svp = 4,
 	dml2_uclk_pstate_change_strategy_force_mall_full_frame = 5,
+	dml2_uclk_pstate_change_strategy_force_alternate = 6,
 };
 
 enum dml2_svp_mode_override {
@@ -474,6 +475,15 @@ struct dml2_display_cfg {
 				bool value;
 			} force_nom_det_size_kbytes;
 
+			struct {
+				bool enable; // So copy time can be forced to 0
+				unsigned int copy_time_us;
+			} force_alt_chan_copy_time;
+
+			struct {
+				bool enable; // So fw delay can be forced to 0
+				unsigned int fw_delay_us;
+			} force_alt_chan_fw_delay;
 			bool mode_support_check_disable;
 			bool mcache_admissibility_check_disable;
 			bool surface_viewport_size_check_disable;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h
index 672b96a3da74..b830e95b27c8 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h
@@ -117,6 +117,7 @@ struct dml2_soc_power_management_parameters {
 	double g6_temp_read_blackout_us[DML_MAX_CLK_TABLE_SIZE];
 	double type_b_dram_clk_change_blackout_us;
 	double type_b_ppt_blackout_us;
+	unsigned int alternate_dram_carveout_size_mb; // size per aperture - assumed same for both apertures for now
 };
 
 struct dml2_clk_table {
@@ -213,6 +214,7 @@ struct dml2_ip_capabilities {
 	unsigned int ppt_max_allow_delay_us;
 	unsigned int temp_read_max_allow_delay_us;
 	unsigned int dummy_pstate_max_allow_delay_us;
+	unsigned int vblank_nom_default_us;
 	/* FAMS2 delays */
 	struct {
 		unsigned int max_allow_delay_us;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h
index f00ca2983ff5..bf71f4e1a451 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h
@@ -20,6 +20,12 @@ enum dml2_project_id {
 	dml2_project_dcn4x_stage2,
 	dml2_project_dcn4x_stage2_auto_drr_svp,
 	dml2_project_dcn42,
+	dml2_project_dcn4x_utm,
+	dml2_project_dcn5x,
+	dml2_project_dcn5x_utm,
+	dml2_project_dcn6x_soc_var_a,
+	dml2_project_dcn6x_soc_var_b,
+	dml2_project_dcn6x = dml2_project_dcn6x_soc_var_b,
 };
 
 enum dml2_pstate_change_support {
@@ -72,6 +78,10 @@ struct dml2_pmo_options {
 	bool disable_dyn_odm_for_multi_stream;
 	bool disable_dyn_odm_for_stream_with_svp;
 	bool force_mandatory_uclk_pstate_support;
+	bool disable_alternate_memory_training;
+	bool force_optional_uclk_pstate_support;
+	bool force_optional_mcache_support;
+	bool force_optional_ppt_temp_read_admissibility;
 	struct dml2_pmo_pstate_strategy *override_strategy_lists[DML2_MAX_PLANES];
 	unsigned int num_override_strategies_per_list[DML2_MAX_PLANES];
 };
@@ -81,6 +91,7 @@ struct dml2_options {
 	struct dml2_pmo_options pmo_options;
 };
 
+struct utm_qos_mode;
 
 struct dml2_initialize_instance_in_out {
 	struct dml2_instance *dml2_instance;
@@ -91,6 +102,7 @@ struct dml2_initialize_instance_in_out {
 	struct {
 		void *explicit_ip_bb;
 		unsigned int explicit_ip_bb_size;
+		const struct utm_qos_model *explicit_qos_model;
 	} overrides;
 };
 
@@ -214,6 +226,7 @@ enum dml2_pstate_method {
 	dml2_pstate_method_reserved_fw_drr_clamped = 20,
 	dml2_pstate_method_fw_drr = 21,
 	dml2_pstate_method_reserved_fw_drr_var = 22,
+	dml2_pstate_method_alternate,
 	dml2_pstate_method_count
 };
 
@@ -369,6 +382,36 @@ struct dml2_mode_support_info {
 	bool dcfclk_support;
 }; // dml2_mode_support_info
 
+struct dml2_memory_path_latency {
+	union {
+		struct {
+			double urgent_ramp;
+			double t_trip;
+			double meta_trip_to_mem;
+			double max_req_latency_urg;
+			double avg_req_latency_urg;
+			double max_req_latency_non_urg;
+			double avg_req_latency_non_urg;
+			double df_response_time_us;
+		} dcn5;
+	};
+};
+
+struct dml2_memory_path_bandwidth {
+	union {
+		struct {
+			double urgent_bandwidth_kbps; // kbytes per sec
+			double non_urgent_bandwidth_kbps; // kbytes per sec
+		} dcn5;
+	};
+};
+
+struct dml2_qos_bound {
+	struct dml2_memory_path_latency latency_ub;
+	struct dml2_memory_path_bandwidth bandwidth_lb;
+	double lsdma_bandwidth_lb_kbps;
+};
+
 struct dml2_display_cfg_programming {
 	struct dml2_display_cfg display_config;
 
@@ -418,6 +461,8 @@ struct dml2_display_cfg_programming {
 		} dcn4x;
 	} min_clocks;
 
+	struct dml2_qos_bound qos_bound;
+	unsigned int min_sop_index;
 	bool uclk_pstate_supported;
 	bool fclk_pstate_supported;
 
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
index 09452f3e49db..72acf12e9251 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
@@ -13094,6 +13094,7 @@ void dml2_core_calcs_get_stream_fams2_programming(const struct dml2_core_interna
 			(uint16_t)stream_pstate_meta->method_subvp.common.allow_end_otg_vline;
 		base_programming->config.bits.clamp_vtotal_min = true;
 		break;
+	case dml2_pstate_method_alternate:
 	case dml2_pstate_method_reserved_hw:
 	case dml2_pstate_method_reserved_fw:
 	case dml2_pstate_method_reserved_fw_drr_clamped:
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c
index 9f1222f5a835..0800c667f204 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c
@@ -4,6 +4,12 @@
 
 #include "dml2_core_factory.h"
 #include "dml2_core_dcn4.h"
+#include "dml2_core_dcn5_funcs_initialize.h"
+#include "dml2_core_dcn5_funcs_mode_support.h"
+#include "dml2_core_dcn5_funcs_mode_programming.h"
+#include "dml2_core_dcn6_funcs_initialize.h"
+#include "dml2_core_dcn6_funcs_mode_support.h"
+#include "dml2_core_dcn6_funcs_mode_programming.h"
 #include "dml2_external_lib_deps.h"
 
 bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance *out)
@@ -36,6 +42,25 @@ bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance
 		out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation;
 		result = true;
 		break;
+	case dml2_project_dcn5x_utm:
+		out->initialize = &dml2_core_dcn5_funcs_initialize;
+		out->validate_solution = &dml2_core_dcn5_funcs_validate_solution;
+		out->populate_programming = &dml2_core_dcn5_funcs_populate_programming;
+		out->populate_informative = &core_dcn4_populate_informative;
+		out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation;
+		result = true;
+		break;
+	case dml2_project_dcn6x_soc_var_a:
+	case dml2_project_dcn6x_soc_var_b:
+		out->initialize = &dml2_core_dcn6_funcs_initialize;
+		out->validate_solution = &dml2_core_dcn6_funcs_validate_solution;
+		out->populate_programming = &dml2_core_dcn6_funcs_populate_programming;
+		out->populate_informative = &core_dcn4_populate_informative;
+		out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation;
+		result = true;
+		break;
+	case dml2_project_dcn4x_utm:
+	case dml2_project_dcn5x:
 	case dml2_project_invalid:
 	default:
 		break;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h
index b8af72392176..8a371bd1a7a5 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_shared_types.h
@@ -14,6 +14,7 @@
 #define __DML2_CALCS_MAX_VRATIO_PRE_OTO__ 4.0 //<brief max vratio for one-to-one prefetch bw scheduling
 #define __DML2_CALCS_MAX_VRATIO_PRE_EQU__ 6.0 //<brief max vratio for equalized prefetch bw scheduling
 #define __DML2_CALCS_MAX_VRATIO_PRE__ 8.0 //<brief max prefetch vratio register limit
+#define __DML2_CALCS_MAX_VSTARTUP__ 1023.0 // <brief max vstartup lines supported by hardware
 
 #define __DML2_CALCS_DPP_INVALID__ 0
 #define __DML2_CALCS_DCFCLK_FACTOR__ 1.15 //<brief fudge factor for min dcfclk calclation
@@ -51,6 +52,7 @@ struct dml2_core_ip_params {
 	unsigned int max_vscl_taps;
 	unsigned int odm_combine_support_mask;
 	unsigned int num_dsc;
+	unsigned int maximum_dsc_slices_per_pipe;
 	unsigned int maximum_dsc_bits_per_component;
 	unsigned int maximum_pixels_per_line_per_dsc_unit;
 	bool dsc422_native_support;
@@ -86,6 +88,7 @@ struct dml2_core_ip_params {
 	unsigned int subvp_swath_height_margin_lines;
 	unsigned int subvp_fw_processing_delay_us;
 	unsigned int subvp_pstate_allow_width_us;
+	unsigned int alt_chan_fw_delay_us; // FW delay value required in mode support calculation
 	// MRQ
 	bool dcn_mrq_present;
 	unsigned int zero_size_buffer_entries;
@@ -96,6 +99,11 @@ struct dml2_core_ip_params {
 
 	unsigned int dchub_arb_to_ret_delay; // num of dcfclk
 	unsigned int hostvm_mode;
+	unsigned int fams2_max_allow_delay_us;
+	unsigned int fams2_min_allow_width_us;
+	unsigned int ppt_max_allow_delay_us;
+	unsigned int temp_read_max_allow_delay_us;
+	bool use_legacy_dsc_delay_formula;
 };
 
 struct dml2_core_internal_DmlPipe {
@@ -335,6 +343,7 @@ struct dml2_core_internal_mode_support_info {
 	double non_urg_bandwidth_required[dml2_core_internal_soc_state_max][dml2_core_internal_bw_max]; // same as urg_bandwidth, except not scaled by urg burst factor
 	double non_urg_bandwidth_required_flip[dml2_core_internal_soc_state_max][dml2_core_internal_bw_max];
 	bool avg_bandwidth_support_ok[dml2_core_internal_soc_state_max][dml2_core_internal_bw_max];
+	struct dml2_memory_path_bandwidth bandwidth_upper_bound;
 	double max_urgent_latency_us;
 	double max_non_urgent_latency_us;
 	double avg_non_urgent_latency_us;
@@ -348,6 +357,7 @@ struct dml2_core_internal_mode_support_info {
 	struct dml2_core_internal_watermarks watermarks;
 	bool dcfclk_support;
 	bool qos_bandwidth_support;
+	bool alternate_channel_size_support;
 };
 
 struct dml2_core_internal_mode_support {
@@ -535,6 +545,7 @@ struct dml2_core_internal_mode_support {
 	double DesiredOutputBpp[DML2_MAX_PLANES];
 	double PixelClockBackEnd[DML2_MAX_PLANES];
 	unsigned int DSCDelay[DML2_MAX_PLANES];
+	bool use_legacy_dsc_delay_formula;
 	enum dml2_core_internal_output_type OutputType[DML2_MAX_PLANES];
 	enum dml2_core_internal_output_type_rate OutputRate[DML2_MAX_PLANES];
 	bool TotalAvailablePipesSupportNoDSC;
@@ -654,6 +665,42 @@ struct dml2_core_internal_mode_support {
 	unsigned int DSTXAfterScaler[DML2_MAX_PLANES];
 
 	enum dml2_pstate_method uclk_pstate_switch_modes[DML2_MAX_PLANES];
+	unsigned int svp0_max_bytes;
+	unsigned int svp1_max_bytes;
+	unsigned int svp0_max_bytes_per_dpp[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp0_max_bytes_per_dpp_c[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp1_max_bytes_per_dpp[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp1_max_bytes_per_dpp_c[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp0_dst_lines[DML2_MAX_PLANES]; // per stream
+	unsigned int svp1_dst_lines[DML2_MAX_PLANES]; // per stream
+	unsigned int svp_req_limit[DML2_MAX_PLANES]; // per stream, should be the same value in time between all streams max(2 swaths, dst_y_pre) over all planes
+	unsigned int nom_req_limit_alt[DML2_MAX_PLANES];
+	unsigned int min_lead_dst_lines[DML2_MAX_PLANES];
+	unsigned int total_swaths[DML2_MAX_PLANES];
+	unsigned int total_swaths_c[DML2_MAX_PLANES];
+	unsigned int prefetch_swaths[DML2_MAX_PLANES];
+	unsigned int prefetch_swaths_c[DML2_MAX_PLANES];
+	double prefetch_hdl_delta[DML2_MAX_PLANES]; // in dst
+	double recout_hdl_delta[DML2_MAX_PLANES]; // in dst
+	double prefetch_hdl_delta_c[DML2_MAX_PLANES]; // in dst
+	double recout_hdl_delta_c[DML2_MAX_PLANES]; // in dst
+	unsigned int max_prefetch_in_lines[DML2_MAX_PLANES]; // max prefetch time over all planes converted to lines for the given stream
+	double lsdma_bw_req_for_alt_kbps;
+
+	// Synchronized timing group assignement
+	unsigned int timing_group_id[DML2_MAX_PLANES]; // timing group id for the given plane
+	unsigned int timing_group_count;
+
+	bool fclk_pstate_required;
+	bool ppt_pstate_required;
+	bool temp_read_pstate_required;
+	// P-state schedule windows
+	double fclk_pstate_allow_start_us[DML2_MAX_PLANES];
+	double fclk_pstate_allow_end_us[DML2_MAX_PLANES];
+	double ppt_pstate_allow_start_us[DML2_MAX_PLANES];
+	double ppt_pstate_allow_end_us[DML2_MAX_PLANES];
+	double temp_read_pstate_allow_start_us[DML2_MAX_PLANES];
+	double temp_read_pstate_allow_end_us[DML2_MAX_PLANES];
 };
 
 /// @brief A mega structure that houses various info for model programming step.
@@ -705,6 +752,7 @@ struct dml2_core_internal_mode_program {
 	double PSCL_THROUGHPUT[DML2_MAX_PLANES];
 	double PSCL_THROUGHPUT_CHROMA[DML2_MAX_PLANES];
 	unsigned int DSCDelay[DML2_MAX_PLANES];
+	bool use_legacy_dsc_delay_formula;
 	double DPPCLKUsingSingleDPP[DML2_MAX_PLANES];
 
 	unsigned int Read256BlockHeightY[DML2_MAX_PLANES];
@@ -845,6 +893,26 @@ struct dml2_core_internal_mode_program {
 	double df_response_time_us;
 
 	enum dml2_pstate_method uclk_pstate_switch_modes[DML2_MAX_PLANES];
+	unsigned int svp0_max_bytes;
+	unsigned int svp1_max_bytes;
+	unsigned int svp0_max_bytes_per_dpp[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp0_max_bytes_per_dpp_c[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp1_max_bytes_per_dpp[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp1_max_bytes_per_dpp_c[DML2_MAX_PLANES]; // max bytes for any DPP under a given plane
+	unsigned int svp0_dst_lines[DML2_MAX_PLANES]; // per stream
+	unsigned int svp1_dst_lines[DML2_MAX_PLANES]; // per stream
+	unsigned int min_lead_dst_lines[DML2_MAX_PLANES]; // per stream, should be max(nominal_req_limit, vstartup_to_vactive). Does not have to be maxed over all planes
+	unsigned int svp_req_limit[DML2_MAX_PLANES]; // per stream, should be the same value in time between all streams max(2 swaths, dst_y_pre) over all planes
+	unsigned int nom_req_limit_alt[DML2_MAX_PLANES]; // per stream
+	unsigned int total_swaths[DML2_MAX_PLANES];
+	unsigned int total_swaths_c[DML2_MAX_PLANES];
+	unsigned int prefetch_swaths[DML2_MAX_PLANES];
+	unsigned int prefetch_swaths_c[DML2_MAX_PLANES];
+	double prefetch_hdl_delta[DML2_MAX_PLANES]; // in dst
+	double recout_hdl_delta[DML2_MAX_PLANES]; // in dst
+	double prefetch_hdl_delta_c[DML2_MAX_PLANES]; // in dst
+	double recout_hdl_delta_c[DML2_MAX_PLANES]; // in dst
+	unsigned int max_prefetch_in_lines[DML2_MAX_PLANES]; // max prefetch time over all planes converted to lines for the given stream
 	// -------------------
 	// Output
 	// -------------------
@@ -1281,6 +1349,7 @@ struct dml2_core_calcs_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport_local
 	double ActiveClockChangeLatencyHidingY;
 	double ActiveClockChangeLatencyHidingC;
 	double ActiveClockChangeLatencyHiding;
+	double peak_vactive_p_vblank_latency_hiding_us;
 	unsigned int dst_y_pstate;
 	unsigned int src_y_pstate_l;
 	unsigned int src_y_pstate_c;
@@ -2180,6 +2249,90 @@ struct dml2_core_calcs_calculate_mcache_setting_params {
 	bool *lc_comb_mcache;
 };
 
+
+struct dml2_core_calcs_calculate_alternate_lead_lines {
+	/* input params */
+	const struct dml2_display_cfg *display_cfg;
+	unsigned int *VStartup;
+	double *VActiveLatencyHidingUs;
+
+	/* output params */
+	unsigned int *min_lead_dst_lines;
+};
+
+struct dml2_core_calcs_calculate_alternate_svp_lines {
+	/* input params */
+	const struct dml2_display_cfg *display_cfg;
+	unsigned int *SwathHeightY;
+	unsigned int *SwathHeightC;
+	unsigned int *DETBufferSizeY;
+	double *BytePerPixelInDETC;
+	double dram_blackout_us;
+
+	/* output params */
+	unsigned int *svp0_dst_lines;
+	unsigned int *svp1_dst_lines;
+	unsigned int *svp_req_limit;
+};
+
+struct dml2_core_calcs_calculate_alternate_params {
+	/* input params */
+	const struct dml2_display_cfg *display_cfg;
+	double *dst_y_prefetch;
+	unsigned int *SwathHeightY;
+	unsigned int *SwathHeightC;
+	unsigned int *SwathWidthY;
+	unsigned int *SwathWidthC;
+	unsigned int *DETBufferSizeY;
+	unsigned int *DETBufferSizeC;
+	unsigned int *BytePerPixelY;
+	unsigned int *BytePerPixelC;
+	double *BytePerPixelInDETY;
+	double *BytePerPixelInDETC;
+	unsigned int *Read256BlockWidthY;
+	unsigned int *Read256BlockHeightY;
+	unsigned int *Read256BlockWidthC;
+	unsigned int *Read256BlockHeightC;
+	unsigned int *MacroTileWidthY;
+	unsigned int *MacroTileWidthC;
+	unsigned int *VInitPrefillY;
+	unsigned int *VInitPrefillC;
+	double *VRatioPrefetchY;
+	double *VRatioPrefetchC;
+	unsigned int *NoOfDPP;
+	unsigned int max_num_dpp;
+	double dram_blackout_us;
+	double *VActiveLatencyHidingUs;
+	unsigned int *svp0_dst_lines;
+	unsigned int *svp1_dst_lines;
+	unsigned int *svp_req_limit;
+	double dcn_non_urgent_bandwidth_kbps;
+	unsigned int alt_chan_fw_delay_us;
+	double *dst_y_per_vm_vblank;
+	double *dst_y_per_row_vblank;
+	unsigned int *DSTYAfterScaler;
+	enum dml2_odm_mode *ODMMode;
+
+	/* output params */
+	unsigned int *svp0_max_bytes;
+	unsigned int *svp1_max_bytes;
+	unsigned int *svp0_max_bytes_per_dpp;
+	unsigned int *svp0_max_bytes_per_dpp_c;
+	unsigned int *svp1_max_bytes_per_dpp;
+	unsigned int *svp1_max_bytes_per_dpp_c;
+	unsigned int *nom_req_limit_alt;
+	unsigned int *min_lead_dst_lines;
+	unsigned int *total_swaths;
+	unsigned int *total_swaths_c;
+	unsigned int *prefetch_swaths;
+	unsigned int *prefetch_swaths_c;
+	double *prefetch_hdl_delta;
+	double *recout_hdl_delta;
+	double *prefetch_hdl_delta_c;
+	double *recout_hdl_delta_c;
+	unsigned int *max_prefetch_in_lines;
+	double *lsdma_bw_req_for_alt_kbps;
+};
 struct dml2_core_calcs_calculate_tdlut_setting_params {
 	// input params
 	double dispclk_mhz;
@@ -2307,6 +2460,9 @@ struct dml2_core_internal_scratch {
 	struct dml2_core_shared_CalculateMetaAndPTETimes_params CalculateMetaAndPTETimes_params;
 	struct dml2_core_calcs_calculate_peak_bandwidth_required_params calculate_peak_bandwidth_params;
 	struct dml2_core_calcs_calculate_bytes_to_fetch_required_to_hide_latency_params calculate_bytes_to_fetch_required_to_hide_latency_params;
+	struct dml2_core_calcs_calculate_alternate_params calculate_alternate_params;
+	struct dml2_core_calcs_calculate_alternate_svp_lines calculate_alternate_svp_lines;
+	struct dml2_core_calcs_calculate_alternate_lead_lines calculate_alternate_lead_lines;
 };
 
 //struct dml2_svp_mode_override;
@@ -2331,6 +2487,7 @@ struct dml2_core_calcs_mode_support_ex {
 	const struct dml2_display_cfg *in_display_cfg;
 	const struct dml2_mcg_min_clock_table *min_clk_table;
 	int min_clk_index;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
 	//unsigned int in_state_index;
 	struct dml2_core_internal_mode_support_info *out_evaluation_info;
 	const enum dml2_pstate_method *uclk_pstate_switch_modes;
@@ -2344,6 +2501,9 @@ struct dml2_core_calcs_mode_programming_ex {
 	const struct dml2_mcg_min_clock_table *min_clk_table;
 	const struct core_display_cfg_support_info *cfg_support_info;
 	int min_clk_index;
+	const struct dml2_uclk_pstate_params *uclk_params;
+	const struct dml2_display_solution *solution;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
 	struct dml2_display_cfg_programming *programming;
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c
index be0517e10104..528ebadb87e1 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c
@@ -5,6 +5,7 @@
 #include "dml2_dpmm_factory.h"
 #include "dml2_dpmm_dcn4.h"
 #include "dml2_external_lib_deps.h"
+#include "dml2_dpmm_dcn5.h"
 
 static bool dummy_map_mode_to_soc_dpm(struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out)
 {
@@ -48,6 +49,17 @@ bool dml2_dpmm_create(enum dml2_project_id project_id, struct dml2_dpmm_instance
 		out->map_watermarks = &dpmm_dcn42_map_watermarks;
 		result = true;
 		break;
+	case dml2_project_dcn5x_utm:
+		out->map_mode_to_soc_dpm = &dpmm_dcn5_map_mode_to_soc_dpm;
+		result = true;
+		break;
+	case dml2_project_dcn6x_soc_var_a:
+	case dml2_project_dcn6x_soc_var_b:
+		/* dpmm is deprecated */
+		result = true;
+		break;
+	case dml2_project_dcn4x_utm:
+	case dml2_project_dcn5x:
 	case dml2_project_invalid:
 	default:
 		break;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c
index 270283332cc1..a1d63148b6e5 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c
@@ -36,6 +36,11 @@ bool dml2_mcg_create(enum dml2_project_id project_id, struct dml2_mcg_instance *
 		out->build_min_clock_table = &mcg_dcn42_build_min_clock_table;
 		result = true;
 		break;
+	case dml2_project_dcn4x_utm:
+	case dml2_project_dcn5x:
+	case dml2_project_dcn5x_utm:
+	case dml2_project_dcn6x_soc_var_a:
+	case dml2_project_dcn6x_soc_var_b:
 	case dml2_project_invalid:
 	default:
 		break;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c
index 8f481ef9316f..7ae02eccd598 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c
@@ -23,6 +23,11 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_1_display[] = {
 		.allow_state_increase = true,
 	},
 
+	// Even-Odd
+	{
+		.per_stream_pstate_method = { dml2_pstate_method_alternate, dml2_pstate_method_na, dml2_pstate_method_na, dml2_pstate_method_na },
+		.allow_state_increase = true,
+	},
 
 	// Then VBlank
 	{
@@ -54,6 +59,11 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_2_display[] = {
 		.allow_state_increase = true,
 	},
 
+	// Even-Odd
+	{
+		.per_stream_pstate_method = { dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_na, dml2_pstate_method_na },
+		.allow_state_increase = true,
+	},
 
 	// Then VActive + VBlank
 	{
@@ -115,6 +125,11 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_3_display[] = {
 		.allow_state_increase = true,
 	},
 
+	// Even-Odd
+	{
+		.per_stream_pstate_method = { dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_na },
+		.allow_state_increase = true,
+	},
 
 	// VActive + 1 VBlank
 	{
@@ -152,6 +167,11 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_4_display[] = {
 		.allow_state_increase = true,
 	},
 
+	// Even-Odd
+	{
+		.per_stream_pstate_method = { dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_alternate, dml2_pstate_method_alternate },
+		.allow_state_increase = true,
+	},
 
 	// VActive + 1 VBlank
 	{
@@ -381,6 +401,7 @@ static enum dml2_pstate_method convert_strategy_to_drr_variant(const enum dml2_p
 	case dml2_pstate_method_reserved_fw:
 	case dml2_pstate_method_reserved_fw_drr_clamped:
 	case dml2_pstate_method_reserved_fw_drr_var:
+	case dml2_pstate_method_alternate:
 	case dml2_pstate_method_count:
 	case dml2_pstate_method_na:
 	default:
@@ -665,6 +686,7 @@ bool pmo_dcn4_fams2_initialize(struct dml2_pmo_initialize_in_out *in_out)
 	pmo->fams_params.v2.drr.refresh_rate_limit_min = 119;
 
 	pmo->options = in_out->options;
+	pmo->options->disable_alternate_memory_training = true;
 
 	/* generate permutations of p-state configs from base strategy list */
 	for (i = 0; i < PMO_DCN4_MAX_DISPLAYS; i++) {
@@ -1204,6 +1226,9 @@ enum dml2_pstate_method dcn4_uclk_pstate_strategy_override_to_pstate_method(cons
 	case dml2_uclk_pstate_change_strategy_force_mall_svp:
 		method = dml2_pstate_method_fw_svp;
 		break;
+	case dml2_uclk_pstate_change_strategy_force_alternate:
+		method = dml2_pstate_method_alternate;
+		break;
 	case dml2_uclk_pstate_change_strategy_force_mall_full_frame:
 	case dml2_uclk_pstate_change_strategy_auto:
 	default:
@@ -1233,6 +1258,9 @@ static enum dml2_uclk_pstate_change_strategy pstate_method_to_uclk_pstate_strate
 	case dml2_pstate_method_fw_drr:
 		override_strategy = dml2_uclk_pstate_change_strategy_force_drr;
 		break;
+	case dml2_pstate_method_alternate:
+		override_strategy = dml2_uclk_pstate_change_strategy_force_alternate;
+		break;
 	case dml2_pstate_method_reserved_hw:
 	case dml2_pstate_method_reserved_fw:
 	case dml2_pstate_method_reserved_fw_drr_clamped:
@@ -1291,6 +1319,7 @@ static struct dml2_pstate_per_method_common_meta *get_per_method_common_meta(
 		break;
 	case dml2_pstate_method_vblank:
 	case dml2_pstate_method_fw_vblank_drr:
+	case dml2_pstate_method_alternate:
 		stream_method_pstate_meta = &pmo->scratch.pmo_dcn4.stream_pstate_meta[stream_idx].method_vblank.common;
 		break;
 	case dml2_pstate_method_fw_svp:
@@ -1609,6 +1638,8 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins
 	unsigned int vactive_stream_mask = 0;
 	unsigned int vblank_count = 0;
 	unsigned int vblank_stream_mask = 0;
+	unsigned int alternate_count = 0;
+	unsigned int alternate_stream_mask = 0;
 
 	bool strategy_matches_forced_requirements = true;
 	bool strategy_matches_drr_requirements = true;
@@ -1640,6 +1671,9 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins
 			pstate_strategy->per_stream_pstate_method[stream_index] == dml2_pstate_method_fw_vblank_drr) {
 			vblank_count++;
 			set_bit_in_bitfield(&vblank_stream_mask, stream_index);
+		} else if (pstate_strategy->per_stream_pstate_method[stream_index] == dml2_pstate_method_alternate) {
+			alternate_count++;
+			set_bit_in_bitfield(&alternate_stream_mask, stream_index);
 		}
 	}
 
@@ -1658,6 +1692,8 @@ static bool validate_pstate_support_strategy_cofunctionality(struct dml2_pmo_ins
 	if (svp_count > 0 && (pmo->options->disable_svp || !all_timings_support_svp(pmo, display_cfg, svp_stream_mask)))
 		return false;
 
+	if (alternate_count > 0 && pmo->options->disable_alternate_memory_training)
+		return false;
 
 	return is_config_schedulable(pmo, display_cfg, pstate_strategy);
 }
@@ -1989,6 +2025,25 @@ static void reset_display_configuration(struct display_configuation_with_meta *d
 	}
 }
 
+static void setup_planes_for_alternate_by_mask(struct display_configuation_with_meta *display_config,
+	struct dml2_pmo_instance *pmo,
+	int plane_mask)
+{
+	(void)pmo;
+	unsigned int plane_index;
+	struct dml2_plane_parameters *plane;
+
+	for (plane_index = 0; plane_index < display_config->display_config.num_planes; plane_index++) {
+		if (is_bit_set_in_bitfield(plane_mask, plane_index)) {
+			plane = &display_config->display_config.plane_descriptors[plane_index];
+
+			// Setup DRR
+			plane->overrides.uclk_pstate_change_strategy = dml2_uclk_pstate_change_strategy_force_alternate;
+
+			display_config->stage3.pstate_switch_modes[plane_index] = dml2_pstate_method_alternate;
+		}
+	}
+}
 
 static void setup_planes_for_drr_by_mask(struct display_configuation_with_meta *display_config,
 	struct dml2_pmo_instance *pmo,
@@ -2168,6 +2223,8 @@ static bool setup_display_config(struct display_configuation_with_meta *display_
 		} else if (scratch->pmo_dcn4.pstate_strategy_candidates[strategy_index].per_stream_pstate_method[stream_index] == dml2_pstate_method_fw_drr) {
 			fams2_required = true;
 			setup_planes_for_drr_by_mask(display_config, pmo, scratch->pmo_dcn4.stream_plane_mask[stream_index]);
+		} else if (scratch->pmo_dcn4.pstate_strategy_candidates[strategy_index].per_stream_pstate_method[stream_index] == dml2_pstate_method_alternate) {
+			setup_planes_for_alternate_by_mask(display_config, pmo, scratch->pmo_dcn4.stream_plane_mask[stream_index]);
 		}
 	}
 
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c
index 21109a19f177..44438792931c 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c
@@ -7,6 +7,8 @@
 #include "dml2_pmo_dcn3.h"
 #include "dml2_pmo_dcn42.h"
 #include "dml2_external_lib_deps.h"
+#include "dml2_pmo_dcn5.h"
+#include "dml2_pmo_dcn6.h"
 
 static bool dummy_init_for_stutter(struct dml2_pmo_init_for_stutter_in_out *in_out)
 {
@@ -94,6 +96,38 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance *
 		out->optimize_for_stutter = pmo_dcn4_fams2_optimize_for_stutter;
 		result = true;
 		break;
+	case dml2_project_dcn5x_utm:
+		out->initialize = dml2_pmo_dcn5_initialize;
+		out->get_ordered_mandatory_stage_optimizers = dml2_pmo_dcn5_get_ordered_mandatory_stage_optimizers;
+		out->get_ordered_optional_stage_optimizers = dml2_pmo_dcn5_get_ordered_optional_stages_optimizers;
+		out->initialize_worksheet = dml2_pmo_dcn5_initialize_worksheet;
+		out->optional_sanity_check = dml2_pmo_dcn5_sanity_check;
+		out->convert_worksheet_to_solution = dml2_pmo_dcn5_convert_worksheet_to_solution;
+		out->clear_pre_validation_states = dml2_pmo_dcn5_clear_pre_validation_states;
+		result = true;
+		break;
+	case dml2_project_dcn6x_soc_var_a:
+		out->initialize = dml2_pmo_dcn6a_initialize;
+		out->get_ordered_mandatory_stage_optimizers = dml2_pmo_dcn6a_get_ordered_mandatory_stage_optimizers;
+		out->get_ordered_optional_stage_optimizers = dml2_pmo_dcn6a_get_ordered_optional_stages_optimizers;
+		out->initialize_worksheet = dml2_pmo_dcn5_initialize_worksheet;
+		out->optional_sanity_check = dml2_pmo_dcn5_sanity_check;
+		out->convert_worksheet_to_solution = dml2_pmo_dcn6_convert_worksheet_to_solution;
+		out->clear_pre_validation_states = dml2_pmo_dcn5_clear_pre_validation_states;
+		result = true;
+		break;
+	case dml2_project_dcn6x_soc_var_b:
+		out->initialize = dml2_pmo_dcn6b_initialize;
+		out->get_ordered_mandatory_stage_optimizers = dml2_pmo_dcn6b_get_ordered_mandatory_stage_optimizers;
+		out->get_ordered_optional_stage_optimizers = dml2_pmo_dcn6b_get_ordered_optional_stages_optimizers;
+		out->initialize_worksheet = dml2_pmo_dcn5_initialize_worksheet;
+		out->optional_sanity_check = dml2_pmo_dcn5_sanity_check;
+		out->convert_worksheet_to_solution = dml2_pmo_dcn6_convert_worksheet_to_solution;
+		out->clear_pre_validation_states = dml2_pmo_dcn5_clear_pre_validation_states;
+		result = true;
+		break;
+	case dml2_project_dcn4x_utm:
+	case dml2_project_dcn5x:
 	case dml2_project_invalid:
 	default:
 		break;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c
index 04860b6790df..aaca0a450f0e 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c
@@ -5,6 +5,7 @@
 #include "dml_top.h"
 #include "dml2_internal_shared_types.h"
 #include "dml2_top_soc15.h"
+#include "dml2_top_utm.h"
 
 unsigned int dml2_get_instance_size_bytes(void)
 {
@@ -19,6 +20,12 @@ bool dml2_initialize_instance(struct dml2_initialize_instance_in_out *in_out)
 	case dml2_project_dcn4x_stage2_auto_drr_svp:
 	case dml2_project_dcn42:
 		return dml2_top_soc15_initialize_instance(in_out);
+	case dml2_project_dcn5x_utm:
+	case dml2_project_dcn6x_soc_var_a:
+	case dml2_project_dcn6x_soc_var_b:
+		return dml2_top_utm_initialize_instance(in_out);
+	case dml2_project_dcn4x_utm:
+	case dml2_project_dcn5x:
 	case dml2_project_invalid:
 	default:
 		return false;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
index 3ae817ea2aad..a18f067fe53f 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h
@@ -8,6 +8,9 @@
 #include "dml2_external_lib_deps.h"
 #include "dml_top_types.h"
 #include "dml2_core_shared_types.h"
+#include "bounding_boxes/utm_qos_model_dchub_v1.h"
+#include "bounding_boxes/utm_qos_model_dchub_v2.h"
+#include "bounding_boxes/utm_qos_model_dchub_v3.h"
 /*
 * DML2 MCG Types and Interfaces
 */
@@ -69,6 +72,153 @@ struct dml2_mcg_build_min_clock_table_params_in_out {
 	*/
 	struct dml2_mcg_min_clock_table *min_clk_table;
 };
+
+struct dml2_soc_operating_point {
+	unsigned int uclk_khz;
+	unsigned int fclk_khz;
+	unsigned int dcfclk_khz;
+	unsigned int socclk_khz;
+};
+
+struct dml2_sop_constraint {
+	union {
+		struct {
+			unsigned int min_sop_index;
+			struct dml2_memory_path_latency latency;
+			struct dml2_soc_operating_point clocks;
+			double min_available_urgent_bandwidth_KBps; // minimum guaranteed urgent bandwidth at active
+		} dcn5;
+	};
+};
+
+struct dml2_sop_table {
+	bool is_initialized;
+	const struct utm_qos_model *model;
+	uint32_t sop_min_available_urgent_bandwidths_KBps[MAX_UTM_SOP_COUNT];
+	uint32_t sop_optimal_dcfclks_khz[MAX_UTM_SOP_COUNT];
+	unsigned int (*get_highest_sop_index)(const struct dml2_sop_table *sop_table);
+	void (*get_sop_constraint_at_index)(const struct dml2_sop_table *sop_table, unsigned int index, struct dml2_sop_constraint *constraint);
+	bool (*is_bw_supported_at_index)(const struct dml2_sop_table *sop_table, const struct dml2_memory_path_bandwidth *bw, unsigned int index);
+	void (*get_max_sop)(const struct dml2_sop_table *sop_table, struct dml2_soc_operating_point *sop);
+	void (*get_min_sop)(const struct dml2_sop_table *sop_table, struct dml2_soc_operating_point *sop);
+};
+
+struct dml2_utm_soc_bb {
+	struct dml2_sop_table sop_table;
+	struct dml2_soc_power_management_parameters power_management_parameters;
+	struct dml2_soc_vmin_clock_limits vmin_limit;
+	struct dml2_dram_params dram_config;
+	struct utm_qos_model qos_model;
+	union {
+		struct utm_qos_model_dchub_v1 qos_model_dchub_v1;
+		struct utm_qos_model_dchub_v2 qos_model_dchub_v2;
+		struct utm_qos_model_dchub_v3 qos_model_dchub_v3;
+	};
+	double lower_bound_bandwidth_dchub;
+	double fraction_of_urgent_bandwidth_nominal_target;
+	double fraction_of_urgent_bandwidth_flip_target;
+	unsigned int dchub_refclk_mhz;
+	unsigned int max_outstanding_reqs;
+	unsigned long return_bus_width_bytes;
+	double phy_downspread_percent;
+	double dcn_downspread_percent;
+	double nominal_sdp_derate_percent;
+	double urgent_sdp_derate_percent;
+	double dispclk_dppclk_vco_speed_mhz;
+	bool no_dfs;
+	unsigned int mem_word_bytes;
+	unsigned int num_dcc_mcaches;
+	unsigned int mcache_size_bytes;
+	unsigned int mcache_line_size_bytes;
+	unsigned int writeback_base_latency_us;
+	unsigned int max_dispclk_khz;
+	unsigned int max_dppclk_khz;
+	unsigned int max_dscclk_khz;
+	unsigned int max_dtbclk_khz;
+	unsigned int max_phyclk_khz;
+	unsigned int max_phyclk_d18_khz;
+	unsigned int max_phyclk_d32_khz;
+	unsigned int min_socclk_khz;
+	unsigned int max_dcfclk_khz;
+	unsigned int min_dcfclk_khz;
+	/* TODO: remove once DML Core no longer depends on max SOP clocks */
+	unsigned int max_uclk_khz;
+	unsigned int max_fclk_khz;
+};
+
+struct dml2_clock_granularity_adjuster;
+struct dml2_cga_initialize_in_out {
+	struct dml2_clock_granularity_adjuster *adjuster;
+	const struct dml2_soc_bb *soc_bb;
+	const struct dml2_core_ip_params *ip;
+};
+
+struct dml2_clock_granularity_adjuster {
+	double dcn_downspread_percent;
+	double dispclk_dppclk_vco_speed_mhz;
+	double dispclk_ramp_margin_percent;
+	double max_dispclk_mhz;
+	void (*initialize)(const struct dml2_cga_initialize_in_out *in_out);
+	double (*adjust_dispclk_mhz)(const struct dml2_clock_granularity_adjuster *adjuster, double dispclk_mhz);
+	void (*adjust_dppclks_mhz)(const struct dml2_clock_granularity_adjuster *adjuster, unsigned int count,
+			const double *dppclks_mhz, double *adjusted_dppclks_mhz, double *adjusted_dpprefclk_mhz);
+	void (*adjust_dtbclks_mhz)(const struct dml2_clock_granularity_adjuster *adjuster, unsigned int count,
+			const double *dtbclks_mhz, double *adjusted_dtbclks_mhz, double *adjusted_dtbrefclk_mhz);
+	double (*adjust_dcfclk_deepsleep_mhz)(const struct dml2_clock_granularity_adjuster *adjuster,
+			double dcfclk_deepsleep_mhz);
+};
+
+#define DML2_STATUS_LIST(FORMAT) \
+	/* Generic */ \
+	FORMAT(DML2_STATUS_OK) \
+	FORMAT(DML2_STATUS_UNKNOWN) \
+	/* Validate */ \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT_PREFETCH) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT_PREFETCH_URGENT) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT_QOS_BANDWIDTH) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_MODE_SUPPORT_DCFCLK) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_PREFETCH) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_MCACHE) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_PMO_SANITY_TOTAL_PIPE_USAGE) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_PMO_SANITY_ODM_DIVISIBILITY) \
+	FORMAT(DML2_STATUS_VALIDATE_FAIL_PSTATE_SCHEDULE) \
+	FORMAT(DML2_STATUS_PSTATE_UNEXPECTED_PSTATE) \
+	FORMAT(DML2_STATUS_PSTATE_NOT_ADMISSIBLE) \
+	/* Optimize */ \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_MCACHE) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_UCLK_PSTATE) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_QOS) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_VMIN) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_STUTTER) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_FCLK_PSTATE_UNSYNCHRONIZABLE_TIMINGS) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_FCLK_PSTATE_INSUFFICENT_HIDING) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_VMIN_DCFCLK) \
+	FORMAT(DML2_STATUS_OPTIMIZE_FAIL_EXCEED_MAX_ITERATION) \
+	/* Populate */ \
+	FORMAT(DML2_STATUS_POPULATE_FAIL_MIN_CLOCK_STATE) \
+	FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING) \
+	FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING_PREFETCH) \
+	FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING_PREFETCH_URGENT) \
+	FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING_FLIP_BANDWIDTH) \
+	FORMAT(DML2_STATUS_POPULATE_FAIL_PROGRAMMING_DCFCLK)
+
+#define ENUM_FORMAT(entry) entry,
+#define CASE_FORMAT(entry) case entry: return #entry;
+
+enum dml2_status {
+	DML2_STATUS_LIST(ENUM_FORMAT)
+};
+
+static inline const char *dml2_status_str(enum dml2_status status)
+{
+	switch (status) {
+		DML2_STATUS_LIST(CASE_FORMAT)
+	}
+
+	return "";
+}
+
 struct dml2_mcg_instance {
 	bool (*build_min_clock_table)(struct dml2_mcg_build_min_clock_table_params_in_out *in_out);
 };
@@ -85,6 +235,8 @@ struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out {
 	struct dml2_soc_bb *soc_bb;
 	struct dml2_mcg_min_clock_table *min_clk_table;
 	const struct display_configuation_with_meta *display_cfg;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
+	const struct dml2_display_solution *solution;
 	struct {
 		bool perform_pseudo_map;
 		struct dml2_core_internal_soc_bb *soc_bb;
@@ -101,6 +253,7 @@ struct dml2_dpmm_map_watermarks_params_in_out {
 	* Input
 	*/
 	const struct display_configuation_with_meta *display_cfg;
+	const struct dml2_display_solution *solution;
 	const struct dml2_core_instance *core;
 
 	/*
@@ -131,6 +284,8 @@ struct dml2_core_initialize_in_out {
 	struct dml2_ip_capabilities *ip_caps;
 
 	struct dml2_mcg_min_clock_table *minimum_clock_table;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
+	const struct dml2_clock_granularity_adjuster *clock_adjuster;
 
 	void *explicit_ip_bb;
 	unsigned int explicit_ip_bb_size;
@@ -169,6 +324,11 @@ struct core_stream_support_info {
 	int vblank_reserved_time_us;
 	int num_dsc_slices;
 	bool dsc_enable;
+	unsigned int alternate_svp0_dst_lines;
+	unsigned int alternate_svp1_dst_lines;
+	unsigned int max_vstartup_lines;
+	unsigned int max_dst_y_after_scaler;
+	unsigned int max_dst_y_prefetch;
 };
 
 struct core_display_cfg_support_info {
@@ -210,6 +370,9 @@ struct dml2_core_mode_support_result {
 
 		unsigned int uclk_pstate_supported;
 		unsigned int fclk_pstate_supported;
+		unsigned int alternate_total_bytes_copy_svp0;
+		unsigned int alternate_total_bytes_copy_svp1;
+		unsigned int lsdma_bw_req_for_alt_kbps;
 		struct dml2_core_internal_watermarks watermarks;
 	} global;
 
@@ -226,6 +389,7 @@ struct dml2_core_mode_support_result {
 	} per_plane[DML2_MAX_PLANES];
 
 	struct core_display_cfg_support_info cfg_support_info;
+	struct dml2_memory_path_bandwidth bandwidth_upper_bound;
 };
 
 struct dml2_optimization_stage1_state {
@@ -305,6 +469,11 @@ struct dml2_pstate_meta {
 		unsigned long phantom_vtotal;
 		struct dml2_pstate_per_method_common_meta common;
 	} method_subvp;
+	struct {
+		int programming_delay_otg_vlines; // DMCUB <-> PMFW delays + any DMCUB/PMFW programming delays required
+		int pmfw_throttle_delay_otg_vlines; // PMFW time it takes to throttle other clients + assert DF P-State allow
+		struct dml2_pstate_per_method_common_meta common;
+	} method_alternate;
 	struct {
 		int programming_delay_otg_vlines;
 		int stretched_vtotal;
@@ -379,6 +548,203 @@ struct dml2_pmo_pstate_strategy {
 	enum dml2_pstate_method per_stream_pstate_method[DML2_MAX_PLANES];
 	bool allow_state_increase;
 };
+
+struct dml2_validation_result {
+	bool is_mode_support_valid;
+	bool is_prefetch_valid;
+	struct dml2_core_mode_support_result mode_support;
+	bool is_mcache_allocation_valid;
+	struct dml2_mcache_surface_allocation mcache_allocations[DML2_MAX_PLANES];
+};
+
+struct dml2_optimization_change {
+	union {
+		struct {
+			bool sop_index				: 1; // bit 0
+			bool mpc_combine_overrides		: 1;
+			bool odm_combine_overrides		: 1;
+			bool reserved_vblank_time		: 1;
+			bool mcache_allocation			: 1;
+			bool uclk_pstate_method			: 1;
+			bool fclk_pstate_support		: 1;
+			bool stutter_support			: 1;
+			bool dcfclk_override			: 1; // bit 8
+			bool ppt_temp_read_pstate_support	: 1;
+			unsigned char reserved			: 6;
+		} bits;
+		unsigned short raw;
+	};
+};
+
+struct dml2_optimization_worksheet {
+	const struct dml2_display_cfg *orig_dispcfg;
+
+	unsigned int timing_group_ids[DML2_MAX_PLANES]; // per plane
+	unsigned int timing_group_count;
+
+	struct {
+		bool is_default_pipe_usage_attempted;
+		bool is_single_stream_odm_case;
+		bool per_plane_status[DML2_MAX_PLANES];
+		struct {
+			int pipe_vp_startx[DML2_MAX_DCN_PIPES];
+			int pipe_vp_endx[DML2_MAX_DCN_PIPES];
+		} plane0;
+		struct {
+			int pipe_vp_startx[DML2_MAX_DCN_PIPES];
+			int pipe_vp_endx[DML2_MAX_DCN_PIPES];
+		} plane1;
+	} mcache;
+
+	struct {
+		unsigned int stream_plane_mask[DML2_MAX_PLANES];
+
+		struct dml2_pstate_meta stream_pstate_meta[DML2_MAX_PLANES]; // per stream
+
+		// Meta-data for implicit SVP generation, indexed by stream index
+		struct dml2_implicit_svp_meta stream_svp_meta[DML2_MAX_PLANES];
+
+		struct dml2_pmo_pstate_strategy pstate_strategy_candidates[DML2_PMO_PSTATE_CANDIDATE_LIST_SIZE];
+		int num_pstate_candidates;
+		int cur_pstate_candidate;
+
+		// Initial value of reserved vblank time as pstate optimize may overwrite and clear current
+		long init_reserved_vblank_time_ns[DML2_MAX_PLANES];
+		unsigned int init_max_vactive_det_fill_delay_us[DML2_MAX_PLANES]; // per plane
+	} uclk_pstate;
+
+	struct {
+		bool is_initialized;
+		bool unoptimizable_streams[DML2_MAX_DCN_PIPES];
+		unsigned int init_odms_used[DML2_MAX_DCN_PIPES];
+	} vmin;
+
+	struct {
+		long init_reserved_vblank_time_ns[DML2_MAX_PLANES];
+		bool should_optimize_z8_stutter;
+		bool is_z8_stutter_attempted;
+		bool should_optimize_stutter;
+		bool is_stutter_attempted;
+	} stutter;
+
+	struct {
+		unsigned int passing_index;
+		unsigned int failing_index;
+		bool is_index0_tested;
+	} qos;
+
+	struct {
+		double max_available_bandwidth_kbps;
+	} dcfclk_vmin;
+
+	struct {
+		bool is_attempted;
+	} fclk_ppt_temp_read_pstate;
+
+	/*
+	 * unified structure for storing current optimization tuning variables. Please only store the final tuning knobs
+	 * we should see exactly what will be optimized in display solution at a quick glance.
+	 */
+	struct dml2_optimization_config {
+		struct  {
+			unsigned int min_sop_index;
+			unsigned int mpc_combine_overrides[DML2_MAX_PLANES]; // per plane
+			unsigned int odm_combine_overrides[DML2_MAX_PLANES]; // per stream
+			long reserved_vblank_time_ns[DML2_MAX_PLANES];
+			struct dml2_mcache_surface_allocation mcache_allocations[DML2_MAX_PLANES];
+
+			bool uclk_pstate_support;
+			enum dml2_pstate_method uclk_pstate_switch_modes[DML2_MAX_PLANES]; // per plane
+			int max_vactive_det_fill_delay_us[DML2_MAX_PLANES][dml2_pstate_type_count]; // per plane
+			// Meta-data for FAMS2
+			bool fams2_required;
+			bool legacy_pstate_info_for_dmu;
+			struct dml2_pstate_meta stream_pstate_meta[DML2_MAX_PLANES]; // per stream
+			bool fclk_pstate_support;
+			bool ppt_temp_read_support;
+			bool stutter_support_in_vblank;
+			bool z8_stutter_support_in_vblank;
+			bool enable_vmin_dcfclk;
+		} config;
+		/* changes that have not yet been validated */
+		struct dml2_optimization_change unvalidated_change;
+	} cur;
+
+	/* post validation */
+	struct dml2_validation_result validation_result;
+};
+
+struct dml2_display_solution {
+	const struct dml2_display_cfg *orig_dispcfg;
+
+	/* current display configuration */
+	struct dml2_display_cfg dispcfg;
+	unsigned int timing_group_ids[DML2_MAX_PLANES]; // per plane
+	unsigned int timing_group_count;
+
+	/* additional DML internally decided configurations */
+	struct dml2_sop_constraint sop_constraint;
+	struct dml2_mcache_surface_allocation mcache_allocations[DML2_MAX_PLANES];
+	struct dml2_uclk_pstate_params {
+		bool support;
+		/* Uclk pstate related*/
+		enum dml2_pstate_method pstate_switch_modes[DML2_MAX_PLANES];
+		// Meta-data for FAMS2
+		bool fams2_required;
+		bool legacy_pstate_info_for_dmu;
+		struct dml2_pstate_meta stream_pstate_meta[DML2_MAX_PLANES]; // per stream
+	} uclk_pstate_params;
+	bool fclk_pstate_support;
+	bool ppt_temp_read_support;
+	bool stutter_support_in_vblank;
+	bool z8_stutter_support_in_vblank;
+
+	/* pre-validation states */
+	struct dml2_optimization_change unvalidated_change;
+
+	/* post validation */
+	struct dml2_validation_result validation_result;
+};
+
+struct dml2_pmo_stage_optimizer {
+	const struct dml2_pmo_instance *pmo;
+	/*
+	 * to optimize stack memory usage, large local variables are pre-allocated in this heap memory. The scope of
+	 * func_locals is bounded by each optimizer's function defined in the union. To share states across an
+	 * optimizer's functions, define it in the dedicated optimizer state in optimization worksheet.
+	 */
+	union dml2_stage_optimizer_function_locals *func_locals;
+	/*
+	 * init interface builds the initial states associated with the current stage optimizer into the worksheet. It
+	 * is for state initialization only. It should not apply new optimization or cause changes to current validation
+	 * result. It is safe to assume that the worksheet passed in or exited from this interface is always validated.
+	 */
+	void (*init)(struct dml2_pmo_stage_optimizer *stage, struct dml2_optimization_worksheet *worksheet);
+	/*
+	 * optimize_next interface controls current optimization's stop conditions. When the interface returns false, it
+	 * means the stage optimizer no longer needs to attempt further optimization. The current worksheet should be
+	 * left unmodified. When the interface returns true, it means the stage optimizer applied new optimization to
+	 * the worksheet. DML top will need to validate and test permissibility again. The worksheet passed in is based
+	 * off the optimization decision from last attempt. It may or may not be validated or permissible. It is upto
+	 * DML top to keep track of the last valid permissible worksheet. This interface is also responsible to clear
+	 * corresponding valid bits in worksheet's validation result based on what optimization it gets applied. When
+	 * the valid bits are cleared, it will be revalidated by top. Otherwise, DML top will assume it is safe to skip
+	 * certain re-validations based on the remaining valid bits. Stage optimizers should clear only the necessary
+	 * valid bits based on the optimization applied to speed up the process.
+	 */
+	bool (*optimize_next)(struct dml2_pmo_stage_optimizer *stage, struct dml2_optimization_worksheet *worksheet);
+	/*
+	 * test_permissibility interface should only check against current optimizer policy specific
+	 * minimum requirements. Test permissibility result is orthogonal to validation result. It is
+	 * safe to assume the worksheet constant passed in is always validated. The interface checks if
+	 * the validated result fulfills the minimum requirements additionally imposed by current stage
+	 * optimizer in order to consider the current optimization as a potential candidate. Stage
+	 * optimizer may still attempt further optimization even if the current one is permissible.
+	 */
+	enum dml2_status (*test_permissibility)(struct dml2_pmo_stage_optimizer *stage,
+			const struct dml2_optimization_worksheet *worksheet);
+};
+
 struct dml2_core_mode_support_in_out {
 	/*
 	* Inputs
@@ -464,9 +830,27 @@ struct dml2_core_internal_state_intermediates {
 	unsigned int dummy;
 };
 
+struct dml2_core_calculate_mp_context {
+	const struct dml2_display_cfg *display_cfg;
+	const struct dml2_core_ip_params *ip;
+	const struct dml2_utm_soc_bb *soc_bb;
+	const struct dml2_core_internal_mode_support *ms;
+	struct dml2_core_calcs_mode_programming_locals *dummies;
+	struct dml2_core_internal_scratch *func_params;
+};
+struct dml2_core_calculate_ms_context {
+	const struct dml2_display_cfg *display_cfg;
+	const struct dml2_core_ip_params *ip;
+	const struct dml2_utm_soc_bb *soc_bb;
+	const struct dml2_clock_granularity_adjuster *clock_adjuster;
+	struct dml2_core_calcs_mode_support_locals *dummies;
+	struct dml2_core_internal_scratch *func_params;
+};
+
 struct dml2_core_mode_support_locals {
 	union {
 		struct dml2_core_calcs_mode_support_ex mode_support_ex_params;
+		struct dml2_core_calculate_ms_context calc_ms_ctx;
 	};
 	struct dml2_display_cfg svp_expanded_display_cfg;
 	struct dml2_calculate_mcache_allocation_in_out calc_mcache_allocation_params;
@@ -475,8 +859,10 @@ struct dml2_core_mode_support_locals {
 struct dml2_core_mode_programming_locals {
 	union {
 		struct dml2_core_calcs_mode_programming_ex mode_programming_ex_params;
+		struct dml2_core_calculate_mp_context calc_mp_ctx;
 	};
 	struct dml2_display_cfg svp_expanded_display_cfg;
+	struct dml2_validation_result temp_result;
 };
 
 struct dml2_core_scratch {
@@ -490,6 +876,8 @@ struct dml2_core_scratch {
 
 struct dml2_core_instance {
 	struct dml2_mcg_min_clock_table *minimum_clock_table;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
+	const struct dml2_clock_granularity_adjuster *clock_adjuster;
 	struct dml2_core_internal_state_inputs inputs;
 	struct dml2_core_internal_state_intermediates intermediates;
 
@@ -497,6 +885,12 @@ struct dml2_core_instance {
 
 	bool (*initialize)(struct dml2_core_initialize_in_out *in_out);
 	bool (*mode_support)(struct dml2_core_mode_support_in_out *in_out);
+	enum dml2_status (*validate_solution)(struct dml2_core_instance *core,
+			const struct dml2_display_solution *solution,
+			struct dml2_validation_result *validation_result);
+	enum dml2_status (*populate_programming)(struct dml2_core_instance *core,
+			const struct dml2_display_solution *solution,
+			struct dml2_display_cfg_programming *programming);
 	bool (*mode_programming)(struct dml2_core_mode_programming_in_out *in_out);
 	bool (*populate_informative)(struct dml2_core_populate_informative_in_out *in_out);
 	bool (*calculate_mcache_allocation)(struct dml2_calculate_mcache_allocation_in_out *in_out);
@@ -520,6 +914,7 @@ struct dml2_pmo_initialize_in_out {
 	struct dml2_ip_capabilities *ip_caps;
 	struct dml2_pmo_options *options;
 	int mcg_clock_table_size;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
 };
 
 struct dml2_pmo_optimize_dcc_mcache_in_out {
@@ -692,6 +1087,35 @@ struct dml2_pmo_scratch {
 			unsigned int sorted_group_gtl_period_index[DML2_MAX_PLANES];
 			double group_phase_offset[DML2_MAX_PLANES];
 		} pmo_dcn4;
+		struct {
+			union dml2_stage_optimizer_function_locals {
+				struct dml2_stage_optimizer_uclk_pstate_init_locals {
+					double allow_delay_us;
+					double blackout_us;
+					double watermark_us;
+
+					unsigned int stream_vactive_capability_mask;
+
+					struct dml2_pmo_pstate_strategy expanded_override_strategy_list[2 * 2 * 2 * 2];
+					unsigned int num_expanded_override_strategies;
+
+					/* mask of synchronized timings by stream index */
+					struct dml2_pmo_synchronized_timing_groups synchronized_timing_groups;
+
+					/* scheduling check locals */
+					struct dml2_scheduling_check_locals scheduling_check_locals;
+				} uclk_pstate_init;
+				struct dml2_stage_optimizer_fclk_ppt_temp_read_pstate_optimize_locals {
+					double pstate_blackout_us;
+					double pstate_watermark_us;
+					double pstate_allow_delay_us;
+
+					struct dml2_pstate_meta per_stream_pstate_meta[DML2_MAX_PLANES];
+					enum dml2_pstate_method per_stream_pstate_method[DML2_MAX_PLANES];
+					struct dml2_scheduling_check_locals scheduling_check_locals;
+				} fclk_ppt_temp_read_pstate_optimize;
+			} func_locals;
+		} pmo_dcn5;
 	};
 };
 
@@ -708,6 +1132,18 @@ struct dml2_pmo_init_data {
 	};
 };
 
+enum dml2_pmo_stage_index {
+	dml2_pmo_stage_index_start = 0,
+	dml2_pmo_stage_index_mcache = dml2_pmo_stage_index_start,
+	dml2_pmo_stage_index_uclk_pstate,
+	dml2_pmo_stage_index_qos,
+	dml2_pmo_stage_index_vmin,
+	dml2_pmo_stage_index_stutter,
+	dml2_pmo_stage_index_vmin_dcfclk,
+	dml2_pmo_stage_index_fclk_ppt_temp_read_pstate,
+	dml2_pmo_stage_index_max,
+};
+
 struct dml2_pmo_instance {
 	struct dml2_soc_bb *soc_bb;
 	struct dml2_ip_capabilities *ip_caps;
@@ -718,6 +1154,7 @@ struct dml2_pmo_instance {
 	int mpc_combine_limit;
 	int odm_combine_limit;
 	int mcg_clock_table_size;
+	const struct dml2_utm_soc_bb *utm_soc_bb;
 	union {
 		struct {
 			struct {
@@ -754,9 +1191,52 @@ struct dml2_pmo_instance {
 	bool (*test_for_stutter)(struct dml2_pmo_test_for_stutter_in_out *in_out);
 	bool (*optimize_for_stutter)(struct dml2_pmo_optimize_for_stutter_in_out *in_out);
 
+	/*
+	 * obtain a list of mandatory stage optimizers ordered by priority. Caller must perform stage optimization in
+	 * the same order.
+	 * return - stage optimizer count
+	 */
+	int (*get_ordered_mandatory_stage_optimizers)(struct dml2_pmo_instance *pmo,
+			struct dml2_pmo_stage_optimizer **optimers);
+	/*
+	 * obtain a list of option stage optimizers ordered by priority, Caller must perform stage optimization in the
+	 * same order. Caller must complete stage optimization for all mandatory stage optimizers before performing
+	 * optional stage optimization.
+	 * return - stage optimizer count
+	 */
+	int (*get_ordered_optional_stage_optimizers)(struct dml2_pmo_instance *pmo,
+			struct dml2_pmo_stage_optimizer **optimers);
+	/*
+	 * initialize an optimization worksheet based on the display config passed in.
+	 */
+	void (*initialize_worksheet)(struct dml2_pmo_instance *pmo,
+			const struct dml2_display_cfg *dispcfg,
+			struct dml2_optimization_worksheet *worksheet);
+	/*
+	 * convert an optimization worksheet to a display solution.
+	 */
+	void (*convert_worksheet_to_solution)(struct dml2_pmo_instance *pmo,
+			const struct dml2_optimization_worksheet *worksheet,
+			struct dml2_display_solution *solution);
+	/*
+	 * when validation is completed with an updated worksheet's validation result, PMO needs to reset pre validation
+	 * states stored in worksheet.
+	 */
+	void (*clear_pre_validation_states)(struct dml2_pmo_instance *pmo,
+			struct dml2_optimization_worksheet *worksheet);
+	/*
+	 * perform a mini validate solution to rule out common optimization config problems after optimize_next is
+	 * called. This interface is a performance optimization to avoid of performing expensive full validate solution
+	 * for common optimization problems. It also generalizes sanity check for all stage optimizers. So the concern
+	 * of sanity check optimization config is isolated out of each stage optimizer.
+	 */
+	enum dml2_status (*optional_sanity_check)(struct dml2_pmo_instance *pmo,
+			const struct dml2_optimization_worksheet *worksheet);
+
 
 	struct dml2_pmo_init_data init_data;
 	struct dml2_pmo_scratch scratch;
+	struct dml2_pmo_stage_optimizer stage_optimizers[dml2_pmo_stage_index_max];
 };
 
 /*
@@ -993,6 +1473,8 @@ struct dml2_instance {
 	struct dml2_ip_capabilities ip_caps;
 
 	struct dml2_mcg_min_clock_table min_clk_table;
+	struct dml2_utm_soc_bb utm_soc_bb;
+	struct dml2_clock_granularity_adjuster clock_adjuster;
 	struct dml2_pmo_options pmo_options;
 	struct dml2_top_funcs funcs;
 
@@ -1002,6 +1484,9 @@ struct dml2_instance {
 		struct dml2_top_mcache_validate_admissability_locals mcache_validate_admissability_locals;
 		struct dml2_check_mode_supported_locals check_mode_supported_locals;
 		struct dml2_build_mode_programming_locals build_mode_programming_locals;
+		struct dml2_optimization_worksheet worksheet;
+		struct dml2_optimization_worksheet worksheet_backup;
+		struct dml2_display_solution solution;
 	} scratch;
 
 	struct {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h
index 2f2ae05dd59c..68ae013b026e 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h
@@ -55,6 +55,12 @@ struct dml2_soc_mall_info {
 	unsigned int mblk_height_8bpe_pixels;
 };
 
+struct dml2_soc_alt_ch_info {
+	unsigned int region_size_bytes[2];
+	/* bits 47:16 of the base address */
+	unsigned int region_base_addr_47_16[2];
+};
+
 // Output of DML2 for clock requirements
 struct dml2_dcn_clocks {
 	unsigned int dispclk_khz;
@@ -204,6 +210,7 @@ enum dml2_force_pstate_methods {
 	dml2_force_pstate_method_vblank,
 	dml2_force_pstate_method_drr,
 	dml2_force_pstate_method_subvp,
+	dml2_force_pstate_method_alternate,
 };
 
 struct dml2_configuration_options {
@@ -226,6 +233,7 @@ struct dml2_configuration_options {
 		struct dml2_dc_svp_callbacks callbacks;
 	} svp_pstate;
 	struct dml2_soc_mall_info mall_cfg;
+	struct dml2_soc_alt_ch_info alt_ch_cfg;
 	struct dml2_soc_bbox_overrides bbox_overrides;
 	unsigned int max_segments_per_hubp;
 	unsigned int det_segment_size;
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h
index debcf308cb3b..a57eb1cd77a6 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h
@@ -749,4 +749,45 @@ void dpp401_set_cursor_matrix(
 	enum dc_color_space color_space,
 	struct dc_csc_transform cursor_csc_color_matrix);
 
+enum dcn401_dscl_mode_sel dpp401_dscl_get_dscl_mode(
+	struct dpp *dpp_base,
+	const struct scaler_data *data,
+	bool dbg_always_scale);
+
+void dpp401_power_on_dscl(
+	struct dpp *dpp_base,
+	bool power_on);
+
+void dpp401_dscl_set_recout(
+	struct dcn401_dpp *dpp,
+	const struct rect *recout);
+
+enum lb_memory_config dpp401_dscl_find_lb_memory_config(
+	struct dcn401_dpp *dpp,
+	const struct scaler_data *scl_data);
+
+void dpp401_dscl_program_isharp(
+	struct dpp *dpp_base,
+	const struct scaler_data *scl_data,
+	bool program_isharp_1dlut,
+	bool *bs_coeffs_updated);
+
+void dpp401_dscl_set_isharp_filter(
+	struct dcn401_dpp *dpp,
+	const uint32_t *filter);
+
+void dpp401_dscl_set_scl_filter(
+	struct dcn401_dpp *dpp,
+	const struct scaler_data *scl_data,
+	bool chroma_coef_mode,
+	bool force_coeffs_update);
+
+void dpp401_dscl_disable_easf(
+	struct dpp *dpp_base,
+	const struct scaler_data *scl_data);
+
+void dpp401_dscl_program_easf(
+	struct dpp *dpp_base,
+	const struct scaler_data *scl_data);
+
 #endif /* __DCN401_DPP_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
index e0ee00c955bc..81f287c89562 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c
@@ -112,7 +112,7 @@ static bool dpp401_dscl_is_420_format(enum dc_pixel_format format)
 		return false;
 }
 
-static enum dcn401_dscl_mode_sel dpp401_dscl_get_dscl_mode(
+enum dcn401_dscl_mode_sel dpp401_dscl_get_dscl_mode(
 		struct dpp *dpp_base,
 		const struct scaler_data *data,
 		bool dbg_always_scale)
@@ -146,7 +146,7 @@ static enum dcn401_dscl_mode_sel dpp401_dscl_get_dscl_mode(
 	return DCN401_DSCL_MODE_SCALING_420_YCBCR_ENABLE;
 }
 
-static void dpp401_power_on_dscl(
+void dpp401_power_on_dscl(
 	struct dpp *dpp_base,
 	bool power_on)
 {
@@ -273,7 +273,7 @@ static void dpp401_dscl_set_scaler_filter(
 
 }
 
-static void dpp401_dscl_set_scl_filter(
+void dpp401_dscl_set_scl_filter(
 		struct dcn401_dpp *dpp,
 		const struct scaler_data *scl_data,
 		bool chroma_coef_mode,
@@ -468,7 +468,7 @@ static bool dpp401_dscl_is_lb_conf_valid(int ceil_vratio, int num_partitions, in
 }
 
 /*find first match configuration which meets the min required lb size*/
-static enum lb_memory_config dpp401_dscl_find_lb_memory_config(struct dcn401_dpp *dpp,
+enum lb_memory_config dpp401_dscl_find_lb_memory_config(struct dcn401_dpp *dpp,
 		const struct scaler_data *scl_data)
 {
 	int num_part_y, num_part_c;
@@ -637,8 +637,8 @@ static void dpp401_dscl_set_manual_ratio_init(
  *
  * Note: This function only have effect if AutoCal is disabled.
  */
-static void dpp401_dscl_set_recout(struct dcn401_dpp *dpp,
-				 const struct rect *recout)
+void dpp401_dscl_set_recout(struct dcn401_dpp *dpp,
+	const struct rect *recout)
 {
 	REG_SET_2(RECOUT_START, 0,
 		  /* First pixel of RECOUT in the active OTG area */
@@ -881,7 +881,7 @@ static void dpp401_dscl_program_easf_h(struct dpp *dpp_base, const struct scaler
  * This is the primary function to program EASF
  *
  */
-static void dpp401_dscl_program_easf(struct dpp *dpp_base, const struct scaler_data *scl_data)
+void dpp401_dscl_program_easf(struct dpp *dpp_base, const struct scaler_data *scl_data)
 {
 	struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
 
@@ -910,7 +910,7 @@ static void dpp401_dscl_program_easf(struct dpp *dpp_base, const struct scaler_d
  * When we have 1:1 scaling, we need to disable EASF
  *
  */
-static void dpp401_dscl_disable_easf(struct dpp *dpp_base, const struct scaler_data *scl_data)
+void dpp401_dscl_disable_easf(struct dpp *dpp_base, const struct scaler_data *scl_data)
 {
 	struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
 
@@ -923,7 +923,7 @@ static void dpp401_dscl_disable_easf(struct dpp *dpp_base, const struct scaler_d
 			SCL_EASF_H_EN, scl_data->dscl_prog_data.easf_h_en);
 	PERF_TRACE();
 }
-static void dpp401_dscl_set_isharp_filter(
+void dpp401_dscl_set_isharp_filter(
 	struct dcn401_dpp *dpp, const uint32_t *filter)
 {
 	int level;
@@ -953,10 +953,10 @@ static void dpp401_dscl_set_isharp_filter(
  * This is the primary function to program isharp
  *
  */
-static void dpp401_dscl_program_isharp(struct dpp *dpp_base,
-		const struct scaler_data *scl_data,
-		bool program_isharp_1dlut,
-		bool *bs_coeffs_updated)
+void dpp401_dscl_program_isharp(struct dpp *dpp_base,
+	const struct scaler_data *scl_data,
+	bool program_isharp_1dlut,
+	bool *bs_coeffs_updated)
 {
 	struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
 	*bs_coeffs_updated = false;
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
index f60e084068c8..eed86f5ae731 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c
@@ -35,10 +35,7 @@ static const uint32_t *get_hist_rgb_luma_coefs(enum dc_color_space color_space)
 	}
 }
 
-static void dpp42_dpp_cm_hist_control(
-	struct dpp *dpp_base,
-	struct cm_hist_control cntl,
-	enum dc_color_space color_space)
+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);
 
@@ -68,7 +65,7 @@ static void dpp42_dpp_cm_hist_control(
 	}
 }
 
-static bool dpp42_dpp_cm_hist_read(struct dpp *dpp_base, struct cm_hist *hist_out)
+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;
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
index f4ee419eabf7..76e2ab10a3a0 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h
@@ -465,5 +465,11 @@ bool dpp42_construct(struct dcn42_dpp *dpp42,
 	const struct dcn42_dpp_shift *tf_shift,
 	const struct dcn42_dpp_mask *tf_mask);
 
+void dpp42_dpp_cm_hist_control(struct dpp *dpp_base,
+	struct cm_hist_control cntl,
+	enum dc_color_space color_space);
+
+bool dpp42_dpp_cm_hist_read(struct dpp *dpp_base,
+	struct cm_hist *hist_out);
 
 #endif /* __DCN42_DPP_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h b/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h
index 4a2bf81286d8..8de9a889886a 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h
+++ b/drivers/gpu/drm/amd/display/dc/gpio/ddc_regs.h
@@ -125,6 +125,8 @@ struct ddc_registers {
 	uint32_t ddc_setup;
 	uint32_t phy_aux_cntl;
 	uint32_t dc_gpio_aux_ctrl_5;
+	uint32_t dc_i3cpad_control0;
+	uint32_t dc_i3cpad_control1;
 };
 
 struct ddc_sh_mask {
@@ -142,6 +144,19 @@ struct ddc_sh_mask {
 	//phy_aux_cntl
 	uint32_t AUX_PAD_RXSEL;
 	uint32_t DDC_PAD_I2CMODE;
+	//dc_i3cpad_control0
+	uint32_t DC_I3CPAD_DDCCLK_MASK;
+	uint32_t DC_I3CPAD_DDCDATA_MASK;
+	uint32_t DC_I3CPAD_PD_EN;
+	uint32_t DC_I3CPAD_CLK_A;
+	uint32_t DC_I3CPAD_DATA_A;
+	uint32_t DC_I3CPAD_CLK_EN;
+	uint32_t DC_I3CPAD_DATA_EN;
+	uint32_t DC_I3CPAD_CLK_Y;
+	uint32_t DC_I3CPAD_DATA_Y;
+	//dc_i3cpad_control1
+	uint32_t DC_I3CPAD_STR;
+	uint32_t DC_I3CPAD_RXSEL;
 };
 
 
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c
index a76884a069e8..b75bfea635fd 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c
@@ -248,3 +248,305 @@ struct hw_gpio_pin *dal_hw_ddc_get_pin(struct gpio *gpio)
 
 	return &hw_ddc->base.base;
 }
+
+static void store_registers_ddc_i3cpad(
+	struct hw_ddc *ddc)
+{
+	switch (ddc->base.base.id) {
+	case GPIO_ID_DDC_DATA:
+		REG_GET(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, &ddc->base.store.mask);
+		REG_GET(dc_i3cpad_control0, DC_I3CPAD_DATA_A, &ddc->base.store.a);
+		REG_GET(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, &ddc->base.store.en);
+		break;
+	case GPIO_ID_DDC_CLOCK:
+		REG_GET(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, &ddc->base.store.mask);
+		REG_GET(dc_i3cpad_control0, DC_I3CPAD_CLK_A, &ddc->base.store.a);
+		REG_GET(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, &ddc->base.store.en);
+		break;
+	default:
+		break;
+	}
+}
+
+static void restore_registers_ddc_i3cpad(
+	struct hw_ddc *ddc)
+{
+	switch (ddc->base.base.id) {
+	case GPIO_ID_DDC_DATA:
+		REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, ddc->base.store.mask);
+		REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, ddc->base.store.a);
+		REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, ddc->base.store.en);
+		break;
+	case GPIO_ID_DDC_CLOCK:
+		REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, ddc->base.store.mask);
+		REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, ddc->base.store.a);
+		REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, ddc->base.store.en);
+		break;
+	default:
+		break;
+	}
+}
+
+bool dal_hw_ddc_open_i3cpad(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode)
+{
+	struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
+
+	store_registers_ddc_i3cpad(ddc);
+
+	ptr->opened = (dal_hw_ddc_config_mode_i3cpad(ddc, mode) == GPIO_RESULT_OK);
+
+	return ptr->opened;
+}
+
+enum gpio_result dal_hw_ddc_get_value_i3cpad(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value)
+{
+	struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
+	enum gpio_result result = GPIO_RESULT_OK;
+
+	switch (ptr->mode) {
+	case GPIO_MODE_INPUT:
+	case GPIO_MODE_OUTPUT:
+	case GPIO_MODE_HARDWARE:
+	case GPIO_MODE_FAST_OUTPUT:
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_GET(dc_i3cpad_control0, DC_I3CPAD_DATA_Y, value);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_GET(dc_i3cpad_control0, DC_I3CPAD_CLK_Y, value);
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		result = GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+	return result;
+}
+
+enum gpio_result dal_hw_ddc_set_value_i3cpad(
+	const struct hw_gpio_pin *ptr,
+	uint32_t value)
+{
+	struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
+
+	switch (ptr->mode) {
+	case GPIO_MODE_OUTPUT:
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, value);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, value);
+			break;
+		default:
+			break;
+		}
+		return GPIO_RESULT_OK;
+	case GPIO_MODE_FAST_OUTPUT:
+		/* We use (EN) to faster switch (used in DDC GPIO).
+		 * So (A) is grounded, output is driven by (EN = 0)
+		 * to pull the line down (output == 0) and (EN=1)
+		 * then output is tri-state */
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, value);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, value);
+			break;
+		default:
+			break;
+		}
+		return GPIO_RESULT_OK;
+	default:
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+}
+
+enum gpio_result dal_hw_ddc_change_mode_i3cpad(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode)
+{
+	struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
+
+	return dal_hw_ddc_config_mode_i3cpad(ddc, mode);
+}
+
+enum gpio_result dal_hw_ddc_config_mode_i3cpad(
+	struct hw_ddc *ddc,
+	enum gpio_mode mode)
+{
+	ddc->base.base.mode = mode;
+
+	switch (mode) {
+	case GPIO_MODE_INPUT:
+		/* turn off output enable, act as input pin;
+		 * program the pin as GPIO, mask out signal driven by HW
+		 */
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_EN, 0);
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 1);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_EN, 0);
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 1);
+			break;
+		default:
+			break;
+		}
+		return GPIO_RESULT_OK;
+
+	case GPIO_MODE_OUTPUT:
+		/* turn on output enable, act as output pin;
+		 * program the pin as GPIO, mask out signal driven by HW
+		 */
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, 0);
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 1);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, 0);
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 1);
+			break;
+		default:
+			break;
+		}
+		return GPIO_RESULT_OK;
+
+	case GPIO_MODE_FAST_OUTPUT:
+		/* grounding the A register then use the EN register bit
+		 * will have faster effect on the rise time
+		 */
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DATA_A, 0);
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 1);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_CLK_A, 0);
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 1);
+			break;
+		default:
+			break;
+		}
+		return GPIO_RESULT_OK;
+
+	case GPIO_MODE_HARDWARE:
+		/* program the pin as tri-state, pin is driven by HW */
+		switch (ddc->base.base.id) {
+		case GPIO_ID_DDC_DATA:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCDATA_MASK, 0);
+			break;
+		case GPIO_ID_DDC_CLOCK:
+			REG_UPDATE(dc_i3cpad_control0, DC_I3CPAD_DDCCLK_MASK, 0);
+			break;
+		default:
+			break;
+		}
+		return GPIO_RESULT_OK;
+
+	default:
+	case GPIO_MODE_INTERRUPT:
+	/* Interrupt mode supported only by HPD (IrqGpio) old pins. */
+		return GPIO_RESULT_NON_SPECIFIC_ERROR;
+	}
+}
+
+static enum gpio_result dal_hw_ddc_set_config_i3cpad(
+	struct hw_gpio_pin *ptr,
+	const struct gpio_config_data *config_data)
+{
+	struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
+
+	switch (config_data->config.ddc.type) {
+	/* For ASICs with i3cpad module there is no dual pad mode for i3cpads */
+	case GPIO_DDC_CONFIG_TYPE_MODE_I2C:
+		/* Enable the RX for the PAD (it is disabled by default). */
+		REG_UPDATE(dc_i3cpad_control1, DC_I3CPAD_RXSEL, 0);
+		return GPIO_RESULT_OK;
+	case GPIO_DDC_CONFIG_TYPE_MODE_AUX:
+		return GPIO_RESULT_OK;
+
+	case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT:
+		REG_UPDATE_3(ddc_setup,
+			DC_I2C_DDC1_ENABLE, 1,
+			DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
+			DC_I2C_DDC1_EDID_DETECT_MODE, 0);
+		return GPIO_RESULT_OK;
+
+	case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT:
+		REG_UPDATE_3(ddc_setup,
+			DC_I2C_DDC1_ENABLE, 1,
+			DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
+			DC_I2C_DDC1_EDID_DETECT_MODE, 1);
+		return GPIO_RESULT_OK;
+
+	case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING:
+		REG_UPDATE_2(ddc_setup,
+			DC_I2C_DDC1_ENABLE, 0,
+			DC_I2C_DDC1_EDID_DETECT_ENABLE, 0);
+		return GPIO_RESULT_OK;
+	}
+
+	BREAK_TO_DEBUGGER();
+	return GPIO_RESULT_NON_SPECIFIC_ERROR;
+}
+
+void dal_hw_ddc_close_i3cpad(
+	struct hw_gpio_pin *ptr)
+{
+	struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
+
+	restore_registers_ddc_i3cpad(ddc);
+
+	ptr->mode = GPIO_MODE_UNKNOWN;
+	ptr->opened = false;
+}
+
+static const struct hw_gpio_pin_funcs funcs_i3cpad = {
+	.destroy = dal_hw_ddc_destroy,
+	.open = dal_hw_ddc_open_i3cpad,
+	.get_value = dal_hw_ddc_get_value_i3cpad,
+	.set_value = dal_hw_ddc_set_value_i3cpad,
+	.set_config = dal_hw_ddc_set_config_i3cpad,
+	.change_mode = dal_hw_ddc_change_mode_i3cpad,
+	.close = dal_hw_ddc_close_i3cpad,
+};
+
+static void dal_hw_ddc_construct_i3cpad(
+	struct hw_ddc *ddc,
+	enum gpio_id id,
+	uint32_t en,
+	struct dc_context *ctx)
+{
+	dal_hw_gpio_construct(&ddc->base, id, en, ctx);
+	ddc->base.base.funcs = &funcs_i3cpad;
+}
+
+void dal_hw_ddc_init_i3cpad(
+	struct hw_ddc **hw_ddc,
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en)
+{
+	if (en > GPIO_DDC_LINE_MAX) {
+		ASSERT_CRITICAL(false);
+		*hw_ddc = NULL;
+	}
+
+	*hw_ddc = kzalloc(sizeof(struct hw_ddc), GFP_KERNEL);
+	if (!*hw_ddc) {
+		ASSERT_CRITICAL(false);
+		return;
+	}
+
+	dal_hw_ddc_construct_i3cpad(*hw_ddc, id, en, ctx);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h
index cc30e65df431..ac2c87d30cf4 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h
@@ -46,4 +46,32 @@ void dal_hw_ddc_init(
 
 struct hw_gpio_pin *dal_hw_ddc_get_pin(struct gpio *gpio);
 
+void dal_hw_ddc_init_i3cpad(
+	struct hw_ddc **hw_ddc,
+	struct dc_context *ctx,
+	enum gpio_id id,
+	uint32_t en);
+
+bool dal_hw_ddc_open_i3cpad(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode);
+
+enum gpio_result dal_hw_ddc_get_value_i3cpad(
+	const struct hw_gpio_pin *ptr,
+	uint32_t *value);
+
+enum gpio_result dal_hw_ddc_set_value_i3cpad(
+	const struct hw_gpio_pin *ptr,
+	uint32_t value);
+
+enum gpio_result dal_hw_ddc_config_mode_i3cpad(
+	struct hw_ddc *ddc,
+	enum gpio_mode mode);
+
+enum gpio_result dal_hw_ddc_change_mode_i3cpad(
+	struct hw_gpio_pin *ptr,
+	enum gpio_mode mode);
+
+void dal_hw_ddc_close_i3cpad(
+	struct hw_gpio_pin *ptr);
 #endif
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
index a907f7d0628b..3300dbc67f32 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
@@ -55,6 +55,7 @@
 #include "dcn401/hw_factory_dcn401.h"
 #include "dcn42/hw_factory_dcn42.h"
 #include "dcn42b/hw_factory_dcn42b.h"
+#include "dcn60/hw_factory_dcn60.h"
 
 bool dal_hw_factory_init(
 	struct hw_factory *factory,
@@ -127,6 +128,9 @@ bool dal_hw_factory_init(
 	case DCN_VERSION_4_2B:
 		dal_hw_factory_dcn42b_init(factory);
 		return true;
+	case DCN_VERSION_6_0:
+		dal_hw_factory_dcn60_init(factory);
+		return true;
 	default:
 		ASSERT_CRITICAL(false);
 		return false;
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
index b58af86dee10..5a231f97aee3 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
@@ -55,6 +55,7 @@
 #include "dcn401/hw_translate_dcn401.h"
 #include "dcn42/hw_translate_dcn42.h"
 #include "dcn42b/hw_translate_dcn42b.h"
+#include "dcn60/hw_translate_dcn60.h"
 
 /*
  * This unit
@@ -128,6 +129,9 @@ bool dal_hw_translate_init(
 	case DCN_VERSION_4_2B:
 		dal_hw_translate_dcn42b_init(translate);
 		return true;
+	case DCN_VERSION_6_0:
+		dal_hw_translate_dcn60_init(translate);
+		return true;
 	default:
 		BREAK_TO_DEBUGGER();
 		return false;
diff --git a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
index 34fc9f56dbef..f3413d743107 100644
--- a/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
+++ b/drivers/gpu/drm/amd/display/dc/hdcp/hdcp_msg.c
@@ -177,6 +177,15 @@ static bool hdmi_14_process_transaction(
 	i2c_command.engine = I2C_COMMAND_ENGINE_HW;//only HW
 	i2c_command.speed = link->ddc->ctx->dc->caps.i2c_speed_in_khz;
 
+	if (link->force_to_use_aux)
+		result = dm_helpers_submit_i2c_over_aux(
+			link->ddc,
+			hdcp_i2c_addr_link_primary,
+			offset,
+			message_info->data,
+			message_info->length,
+			hdcp_cmd_is_read[message_info->msg_id]);
+	else
 	result = dm_helpers_submit_i2c(
 			link->ctx,
 			link,
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
index ff9a1ae29474..accb79c6dde5 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
@@ -201,6 +201,20 @@ struct dcn_hubbub_registers {
 	uint32_t DCHUBBUB_TIMEOUT_DETECTION_CTRL1;
 	uint32_t DCHUBBUB_TIMEOUT_DETECTION_CTRL2;
 	uint32_t DCHUBBUB_CTRL_STATUS;
+	uint32_t DCHUBBUB_ARB_BUFFER_FULLNESS_WATERMARK_A;
+	uint32_t DCHUBBUB_ARB_BUFFER_FULLNESS_WATERMARK_B;
+	uint32_t DCHUBBUB_PERFORMANCE_MEASUREMENT_CNTL;
+	uint32_t DCHUBBUB_PERFORMANCE_MEASUREMENT_CNTL2;
+	uint32_t DC_PERFMON5_PERFCOUNTER_CNTL;
+	uint32_t DC_PERFMON5_PERFCOUNTER_CNTL2;
+	uint32_t DC_PERFMON5_PERFCOUNTER_STATE;
+	uint32_t DC_PERFMON5_PERFMON_CNTL;
+	uint32_t DC_PERFMON5_PERFMON_CNTL2;
+	uint32_t DC_PERFMON5_PERFMON_CVALUE_INT_MISC;
+	uint32_t DC_PERFMON5_PERFMON_CVALUE_LOW;
+	uint32_t DC_PERFMON5_PERFMON_HI;
+	uint32_t DC_PERFMON5_PERFMON_LOW;
+	uint32_t FMON_CTRL;
 };
 
 #define HUBBUB_REG_FIELD_LIST_DCN32(type) \
@@ -443,6 +457,96 @@ struct dcn_hubbub_registers {
 
 #define HUBBUB_REG_FIELD_LIST_DCN4_2(type) \
 	type URGENT_ZERO_SIZE_REQ_EN
+
+#define HUBBUB_PERFMON_REG_FIELD_LIST(type) \
+		type DCHUBBUB_LATENCY_CNT_EN;\
+		type DCHUBBUB_DF_REQ_CMD_LATENCY_SEL;\
+		type ARB_LATENCY_PIPE_SEL;\
+		type ARB_LATENCY_REQ_TYPE_SEL;\
+		type ROB_FIFO_LEVEL;\
+		type REQ_UNIT_ID_MASK;\
+		type REQ_UNIT_ID_SEL;\
+		type DCHUBBUB_LATENCY_FRAME_WIN_EN;\
+		type DCHUBBUB_LATENCY_FRAME_WIN_SRC_SEL;\
+		type DCHUBBUB_LATENCY_FRAME_WIN_DUR;\
+		type LATENCY_SOURCE_SEL;\
+		type LATENCY_DEBUG_SEL;\
+		type UTM_FILTER_SEL;\
+		type ROB_MAX_FIFO_LEVEL;\
+		type ROB_MAX_FIFO_LEVEL_RESET;\
+		type PERFCOUNTER_EVENT_SEL;\
+		type PERFCOUNTER_CVALUE_SEL;\
+		type PERFCOUNTER_INC_MODE;\
+		type PERFCOUNTER_HW_CNTL_SEL;\
+		type PERFCOUNTER_RUNEN_MODE;\
+		type PERFCOUNTER_CNTOFF_START_DIS;\
+		type PERFCOUNTER_RESTART_EN;\
+		type PERFCOUNTER_INT_EN;\
+		type PERFCOUNTER_OFF_MASK;\
+		type PERFCOUNTER_ACTIVE;\
+		type PERFCOUNTER_CNTL_SEL;\
+		type PERFCOUNTER_COUNTED_VALUE_TYPE;\
+		type PERFCOUNTER_HW_STOP1_SEL;\
+		type PERFCOUNTER_HW_STOP2_SEL;\
+		type PERFCOUNTER_CNTOFF_SEL;\
+		type PERFCOUNTER_CNTL2_SEL;\
+		type PERFCOUNTER_CNT0_STATE;\
+		type PERFCOUNTER_STATE_SEL0;\
+		type PERFCOUNTER_CNT1_STATE;\
+		type PERFCOUNTER_STATE_SEL1;\
+		type PERFCOUNTER_CNT2_STATE;\
+		type PERFCOUNTER_STATE_SEL2;\
+		type PERFCOUNTER_CNT3_STATE;\
+		type PERFCOUNTER_STATE_SEL3;\
+		type PERFCOUNTER_CNT4_STATE;\
+		type PERFCOUNTER_STATE_SEL4;\
+		type PERFCOUNTER_CNT5_STATE;\
+		type PERFCOUNTER_STATE_SEL5;\
+		type PERFCOUNTER_CNT6_STATE;\
+		type PERFCOUNTER_STATE_SEL6;\
+		type PERFCOUNTER_CNT7_STATE;\
+		type PERFCOUNTER_STATE_SEL7;\
+		type PERFMON_STATE;\
+		type PERFMON_RPT_COUNT;\
+		type PERFMON_CNTOFF_AND_OR;\
+		type PERFMON_CNTOFF_INT_EN;\
+		type PERFMON_CNTOFF_INT_STATUS;\
+		type PERFMON_CNTOFF_INT_ACK;\
+		type PERFMON_CNTOFF_INT_TYPE;\
+		type PERFMON_CLK_ENABLE;\
+		type PERFMON_RUN_ENABLE_START_SEL;\
+		type PERFMON_RUN_ENABLE_STOP_SEL;\
+		type PERFCOUNTER_INT0_STATUS;\
+		type PERFCOUNTER_INT1_STATUS;\
+		type PERFCOUNTER_INT2_STATUS;\
+		type PERFCOUNTER_INT3_STATUS;\
+		type PERFCOUNTER_INT4_STATUS;\
+		type PERFCOUNTER_INT5_STATUS;\
+		type PERFCOUNTER_INT6_STATUS;\
+		type PERFCOUNTER_INT7_STATUS;\
+		type PERFCOUNTER_INT0_ACK;\
+		type PERFCOUNTER_INT1_ACK;\
+		type PERFCOUNTER_INT2_ACK;\
+		type PERFCOUNTER_INT3_ACK;\
+		type PERFCOUNTER_INT4_ACK;\
+		type PERFCOUNTER_INT5_ACK;\
+		type PERFCOUNTER_INT6_ACK;\
+		type PERFCOUNTER_INT7_ACK;\
+		type PERFMON_CVALUE_HI;\
+		type PERFMON_CVALUE_LOW;\
+		type PERFMON_HI;\
+		type PERFMON_READ_SEL;\
+		type PERFMON_LOW;\
+		type FMON_MODE;\
+		type DCHUBBUB_ARB_UTM_FORCE_URGENT;\
+		type DCHUBBUB_ARB_UTM_FORCE_BANDWIDTH_OVERHEAD;\
+		type DCHUBBUB_ARB_UTM_FORCE_ENABLE;\
+		type DCHUBBUB_ARB_DO_NOT_FORCE_URGENCY_DURING_PSTATE_CHANGE_REQUEST
+
+#define HUBBUB_REG_FIELD_LIST_DCN60(type) \
+		type DCHUBBUB_ARB_BUFFER_FULLNESS_WATERMARK_A;\
+		type DCHUBBUB_ARB_BUFFER_FULLNESS_WATERMARK_B
+
 struct dcn_hubbub_shift {
 	DCN_HUBBUB_REG_FIELD_LIST(uint8_t);
 	HUBBUB_STUTTER_REG_FIELD_LIST(uint8_t);
@@ -453,6 +557,8 @@ struct dcn_hubbub_shift {
 	HUBBUB_REG_FIELD_LIST_DCN4_01(uint8_t);
 	HUBBUB_REG_FIELD_LIST_DCN4_2(uint8_t);
 
+	HUBBUB_REG_FIELD_LIST_DCN60(uint8_t);
+	HUBBUB_PERFMON_REG_FIELD_LIST(uint8_t);
 };
 
 struct dcn_hubbub_mask {
@@ -465,6 +571,8 @@ struct dcn_hubbub_mask {
 	HUBBUB_REG_FIELD_LIST_DCN4_01(uint32_t);
 	HUBBUB_REG_FIELD_LIST_DCN4_2(uint8_t);
 
+	HUBBUB_REG_FIELD_LIST_DCN60(uint32_t);
+	HUBBUB_PERFMON_REG_FIELD_LIST(uint32_t);
 };
 
 struct dc;
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h
index 2595c6441f00..ea90dee05d5f 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h
@@ -182,6 +182,9 @@
 	uint32_t DCHUBP_ADDR_CONFIG;\
 	uint32_t HUBP_MALL_STATUS
 
+#define DCN60_HUBP_REG_VARIABLE_LIST \
+	uint32_t DCSURF_LEGACY_ADDR_CONFIG;\
+	uint32_t DST_Y_ALT_CH_DRQ_LIMIT
 #define DCN2_HUBP_REG_FIELD_VARIABLE_LIST(type) \
 	DCN_HUBP_REG_FIELD_BASE_LIST(type); \
 	type DMDATA_ADDRESS_HIGH;\
@@ -293,18 +296,44 @@
 	type HUBP_3DLUT_CROSSBAR_SEL_G;\
 	type HUBP_3DLUT_CROSSBAR_SEL_B;\
 	type HUBP_3DLUT_CROSSBAR_SEL_R
+#define DCN60_HUBP_REG_FIELD_VARIABLE_LIST(type) \
+	type COMPAT_LEVEL; \
+	type LEGACY_PIPE_INTERLEAVE;\
+	type ARRAY_MODE;\
+	type PIPE_CONFIG;\
+	type MICRO_TILE_MODE_NEW;\
+	type TILE_SPLIT; \
+	type BANK_WIDTH; \
+	type BANK_HEIGHT;\
+	type MACRO_TILE_ASPECT;\
+	type LEGACY_NUM_BANKS;\
+	type FORCE_URGENT_FLIP;\
+	type FORCE_URGENT_VM_PREFETCH;\
+	type URGENT_FORCE_VALUE;\
+	type URGENT_FORCE_EN;\
+	type FORCE_DISP_PREF_TO_VBLANK;\
+	type DST_Y_ALT_CH_DRQ_LIMIT;\
+	type FORCE_CURSOR_TO_DISP_PREF
+/*
+	type HUBP_3DLUT_CROSSBAR_SEL_B;\
+	type HUBP_3DLUT_CROSSBAR_SEL_G;\
+	type HUBP_3DLUT_CROSSBAR_SEL_R;
+*/
 struct dcn_hubp2_registers {
 	DCN401_HUBP_REG_COMMON_VARIABLE_LIST;
+	DCN60_HUBP_REG_VARIABLE_LIST;
 };
 
 struct dcn_hubp2_shift {
 	DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t);
 	DCN42_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t);
+	DCN60_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t);
 };
 
 struct dcn_hubp2_mask {
 	DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t);
 	DCN42_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t);
+	DCN60_HUBP_REG_FIELD_VARIABLE_LIST(uint32_t);
 };
 
 struct dcn20_hubp {
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h
index dc8feca578c5..2cc4e7516a5d 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h
@@ -702,6 +702,7 @@ struct dce_hwseq_registers {
 	uint32_t DOMAIN25_PG_STATUS;
 	uint32_t DOMAIN26_PG_CONFIG;
 	uint32_t DOMAIN26_PG_STATUS;
+	uint32_t HDCP_INTERRUPT_DEST;
 };
  /* set field name */
 #define HWS_SF(blk_name, reg_name, field_name, post_fix)\
@@ -1254,6 +1255,12 @@ struct dce_hwseq_registers {
 	type DOMAIN26_POWER_GATE; \
 	type DOMAIN26_PGFSM_PWR_STATUS;
 
+#define HWSEQ_DCN60_REG_FIELD_LIST(type) \
+	type DOUT_IHC_HDCP0_I2C_XFER_REQ_INTERRUPT_DEST; \
+	type DOUT_IHC_HDCP1_I2C_XFER_REQ_INTERRUPT_DEST; \
+	type DOUT_IHC_HDCP2_I2C_XFER_REQ_INTERRUPT_DEST; \
+	type DOUT_IHC_HDCP3_I2C_XFER_REQ_INTERRUPT_DEST;
+
 struct dce_hwseq_shift {
 	HWSEQ_REG_FIELD_LIST(uint8_t)
 	HWSEQ_DCN_REG_FIELD_LIST(uint8_t)
@@ -1263,6 +1270,7 @@ struct dce_hwseq_shift {
 	HWSEQ_DCN35_REG_FIELD_LIST(uint8_t)
 	HWSEQ_DCN401_REG_FIELD_LIST(uint8_t)
 	HWSEQ_DCN42_REG_FIELD_LIST(uint8_t)
+	HWSEQ_DCN60_REG_FIELD_LIST(uint8_t)
 };
 
 struct dce_hwseq_mask {
@@ -1274,6 +1282,7 @@ struct dce_hwseq_mask {
 	HWSEQ_DCN35_REG_FIELD_LIST(uint32_t)
 	HWSEQ_DCN401_REG_FIELD_LIST(uint32_t)
 	HWSEQ_DCN42_REG_FIELD_LIST(uint32_t)
+	HWSEQ_DCN60_REG_FIELD_LIST(uint32_t)
 };
 
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
index f91ce2b4b1bf..5fcf30b448a5 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
@@ -3487,6 +3487,17 @@ void dce110_enable_tmds_link_output(struct dc_link *link,
 			signal,
 			pixel_clock);
 	link->phy_state.symclk_state = SYMCLK_ON_TX_ON;
+
+	// For dongle Type 2 with no I2C support on board, setup sw mode of Ri/Pj check with proper aux instance
+	if (link->force_to_use_aux) {
+		if (link->link_enc && link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode)
+			link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode(link->link_enc,
+				link->aux_hw_inst, true);
+	} else
+		// For HDMI setup hw mode of Ri/Pj check with proper ddc pin instance
+		if (link->link_enc && link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode)
+			link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode(link->link_enc,
+				link->ddc_hw_inst, false);
 }
 
 static void dce110_enable_analog_link_output(
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
index 22c7535fd9c4..097e4ac2df05 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
@@ -524,7 +524,7 @@ static void dcn10_log_color_state(struct dc *dc,
 	DTN_INFO("DPP Color Caps: input_lut_shared:%d  icsc:%d"
 		 "  dgam_ram:%d  dgam_rom: srgb:%d,bt2020:%d,gamma2_2:%d,pq:%d,hlg:%d"
 		 "  post_csc:%d  gamcor:%d  dgam_rom_for_yuv:%d  3d_lut:%d"
-		 "  blnd_lut:%d  oscs:%d\n\n",
+		 "  upsp_pre_scaler:%d  blnd_lut:%d  oscs:%d\n\n",
 		 dc->caps.color.dpp.input_lut_shared,
 		 dc->caps.color.dpp.icsc,
 		 dc->caps.color.dpp.dgam_ram,
@@ -537,6 +537,7 @@ static void dcn10_log_color_state(struct dc *dc,
 		 dc->caps.color.dpp.gamma_corr,
 		 dc->caps.color.dpp.dgam_rom_for_yuv,
 		 dc->caps.color.dpp.hw_3d_lut,
+		 dc->caps.color.dpp.upsp_pre_scaler,
 		 dc->caps.color.dpp.ogam_ram,
 		 dc->caps.color.dpp.ocsc);
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index 98778d5e114e..16bb6f678567 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -148,7 +148,7 @@ void dcn20_log_color_state(struct dc *dc,
 	DTN_INFO("DPP Color Caps: input_lut_shared:%d  icsc:%d"
 		 "  dgam_ram:%d  dgam_rom: srgb:%d,bt2020:%d,gamma2_2:%d,pq:%d,hlg:%d"
 		 "  post_csc:%d  gamcor:%d  dgam_rom_for_yuv:%d  3d_lut:%d"
-		 "  blnd_lut:%d  oscs:%d\n\n",
+		 "  upsp_pre_scaler:%d  blnd_lut:%d  oscs:%d\n\n",
 		 dc->caps.color.dpp.input_lut_shared,
 		 dc->caps.color.dpp.icsc,
 		 dc->caps.color.dpp.dgam_ram,
@@ -161,6 +161,7 @@ void dcn20_log_color_state(struct dc *dc,
 		 dc->caps.color.dpp.gamma_corr,
 		 dc->caps.color.dpp.dgam_rom_for_yuv,
 		 dc->caps.color.dpp.hw_3d_lut,
+		 dc->caps.color.dpp.upsp_pre_scaler,
 		 dc->caps.color.dpp.ogam_ram,
 		 dc->caps.color.dpp.ocsc);
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
index 59184e146fc9..cb163902e12e 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
@@ -157,7 +157,7 @@ void dcn30_log_color_state(struct dc *dc,
 	DTN_INFO("DPP Color Caps: input_lut_shared:%d  icsc:%d"
 		 "  dgam_ram:%d  dgam_rom: srgb:%d,bt2020:%d,gamma2_2:%d,pq:%d,hlg:%d"
 		 "  post_csc:%d  gamcor:%d  dgam_rom_for_yuv:%d  3d_lut:%d"
-		 "  blnd_lut:%d  oscs:%d\n\n",
+		 "  upsp_pre_scaler:%d  blnd_lut:%d  oscs:%d\n\n",
 		 dc->caps.color.dpp.input_lut_shared,
 		 dc->caps.color.dpp.icsc,
 		 dc->caps.color.dpp.dgam_ram,
@@ -170,6 +170,7 @@ void dcn30_log_color_state(struct dc *dc,
 		 dc->caps.color.dpp.gamma_corr,
 		 dc->caps.color.dpp.dgam_rom_for_yuv,
 		 dc->caps.color.dpp.hw_3d_lut,
+		 dc->caps.color.dpp.upsp_pre_scaler,
 		 dc->caps.color.dpp.ogam_ram,
 		 dc->caps.color.dpp.ocsc);
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index c5f6eb482f07..51fd2b3fe106 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -544,7 +544,10 @@ bool dcn32_set_input_transfer_func(struct dc *dc,
 	if (plane_state->in_transfer_func.type == TF_TYPE_PREDEFINED)
 		tf = plane_state->in_transfer_func.tf;
 
-	dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf);
+	if (dpp_base->funcs->dpp_set_pregam_state)
+		dpp_base->funcs->dpp_set_pregam_state(dpp_base, tf, plane_state->scaling_linearity);
+	else
+		dpp_base->funcs->dpp_set_pre_degam(dpp_base, tf);
 
 	if (plane_state->in_transfer_func.type == TF_TYPE_HWPWL)
 		params = &plane_state->in_transfer_func.pwl;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
index f14c39a643da..08f1f307657c 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
@@ -48,6 +48,7 @@
 #include "dpcd_defs.h"
 #include "dce/dmub_outbox.h"
 #include "link_service.h"
+#include "dce/dmub_hw_lock_mgr.h"
 #include "dcn10/dcn10_hwseq.h"
 #include "inc/link_enc_cfg.h"
 #include "dcn30/dcn30_vpg.h"
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index fa9a5d8065d3..b89010a88b44 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -348,6 +348,11 @@ void dcn401_init_hw(struct dc *dc)
 					dal_gpio_destroy_ddc(&ddc_pin);
 				}
 			}
+		//Setup corresponding HDCP XFER DEST interrupt to go to DMUCB
+		dc_dmub_srv_ihc_set_dig_hdcp_interrupt_dest(
+			dc->ctx->dmub_srv,
+			link->eng_id,
+			true);
 		}
 	}
 
@@ -1099,6 +1104,12 @@ void dcn401_disable_link_output(struct dc_link *link,
 		dmcu->funcs->lock_phy(dmcu);
 
 	if (dc_is_tmds_signal(signal) && link->phy_state.symclk_ref_cnts.otg > 0) {
+		// Disable interrupt, setup default hw mode of Ri/Pj check with proper aux instance
+		if (link->force_to_use_aux) {
+			if (link->link_enc && link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode)
+				link->link_enc->funcs->setup_ri_pj_check_in_sw_or_hw_mode(link->link_enc,
+					link->aux_hw_inst, false);
+		}
 		disable_link_output_symclk_on_tx_off(link, DP_UNKNOWN_ENCODING);
 		link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
 	} else {
@@ -2609,6 +2620,16 @@ void dcn401_program_front_end_for_ctx(
 
 	if (resource_is_pipe_topology_changed(dc->current_state, context))
 		resource_log_pipe_topology_update(dc, context);
+	if (dc->debug.enable_block_sequence_programming) {
+		hwss_build_full_sequence(dc,
+			context->block_sequence,
+			&(context->block_sequence_steps),
+			context, false);
+		hwss_execute_sequence(dc,
+			context->block_sequence,
+			context->block_sequence_steps);
+		return;
+	}
 
 	if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
 		for (i = 0; i < dc->res_pool->pipe_count; i++) {
@@ -2770,6 +2791,17 @@ void dcn401_post_unlock_program_front_end(
 	struct dce_hwseq *hwseq = dc->hwseq;
 	unsigned int i;
 
+	if (dc->debug.enable_block_sequence_programming) {
+		hwss_build_post_unlock_full_sequence(dc,
+			context->block_sequence,
+			&(context->block_sequence_steps),
+			context);
+		hwss_execute_sequence(dc,
+			context->block_sequence,
+			context->block_sequence_steps);
+		return;
+	}
+
 	for (i = 0; i < dc->res_pool->pipe_count; i++)
 		if (resource_is_pipe_type(&dc->current_state->res_ctx.pipe_ctx[i], OPP_HEAD) &&
 			!resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], OPP_HEAD))
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index 4549c435501a..c4296b8390f2 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -145,6 +145,9 @@ struct set_output_transfer_func_params {
 	bool is_top_pipe;
 	const struct dc_stream_state *stream;
 };
+struct program_upsp_params {
+	struct pipe_ctx *pipe_ctx;
+};
 
 struct update_visual_confirm_params {
 	struct dc *dc;
@@ -1030,6 +1033,7 @@ union block_sequence_params {
 	struct setup_dpp_params setup_dpp_params;
 	struct program_bias_and_scale_params program_bias_and_scale_params;
 	struct set_output_transfer_func_params set_output_transfer_func_params;
+	struct program_upsp_params program_upsp_params;
 	struct update_visual_confirm_params update_visual_confirm_params;
 	struct power_on_mpc_mem_pwr_params power_on_mpc_mem_pwr_params;
 	struct set_output_csc_params set_output_csc_params;
@@ -1207,6 +1211,7 @@ enum block_sequence_func {
 	DPP_PROGRAM_BIAS_AND_SCALE,
 	DPP_SET_OUTPUT_TRANSFER_FUNC,
 	DPP_SET_HDR_MULTIPLIER,
+	DPP_PROGRAM_UPSP,
 	MPC_UPDATE_VISUAL_CONFIRM,
 	MPC_POWER_ON_MPC_MEM_PWR,
 	MPC_SET_OUTPUT_CSC,
@@ -1783,6 +1788,16 @@ void hwss_build_fast_sequence(struct dc *dc,
 		struct dc_stream_status *stream_status,
 		struct dc_state *context);
 
+void hwss_build_full_sequence(struct dc *dc,
+	struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE],
+	unsigned int *num_steps,
+	struct dc_state *context, bool program_phantom_pipe);
+
+void hwss_build_post_unlock_full_sequence(struct dc *dc,
+	struct block_sequence block_sequence[MAX_HWSS_BLOCK_SEQUENCE_SIZE],
+	unsigned int *num_steps,
+	struct dc_state *context);
+
 void hwss_wait_for_all_blank_complete(struct dc *dc,
 		struct dc_state *context);
 
@@ -1806,6 +1821,8 @@ void hwss_setup_dpp(union block_sequence_params *params);
 
 void hwss_program_bias_and_scale(union block_sequence_params *params);
 
+void hwss_program_upsp(union block_sequence_params *params);
+
 void hwss_power_on_mpc_mem_pwr(union block_sequence_params *params);
 
 void hwss_set_output_csc(union block_sequence_params *params);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
index e87f9fd60bcb..b18d607fb222 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -447,6 +447,7 @@ enum p_state_switch_method {
 	P_STATE_SUB_VP,
 	P_STATE_DRR_SUB_VP,
 	P_STATE_V_BLANK_SUB_VP,
+	P_STATE_ALT,
 };
 
 struct dsc_padding_params {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
index 23c9798936c2..d735eb1e7f43 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
@@ -293,6 +293,27 @@ enum dentist_divider_range {
 	CLK_SF(CLK5_CLK2_DS_CNTL, CLK2_ALLOW_DS, mask_sh), \
 	CLK_SF(CLK5_CLK3_DS_CNTL, CLK3_ALLOW_DS, mask_sh)
 
+#define CLK_REG_LIST_DCN60()	  \
+	CLK_SR_DCN60(CLK8_CLK_TICK_CNT_CONFIG_REG,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK0_CURRENT_CNT,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK1_CURRENT_CNT,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK2_CURRENT_CNT,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK3_CURRENT_CNT,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK4_CURRENT_CNT,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK0_BYPASS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK1_BYPASS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK2_BYPASS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK3_BYPASS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK4_BYPASS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK0_DS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK1_DS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK2_DS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK3_DS_CNTL,  CLK08, 0), \
+	CLK_SR_DCN60(CLK8_CLK4_DS_CNTL,  CLK08, 0)
+
+#define CLK_COMMON_MASK_SH_LIST_DCN60(mask_sh) \
+	CLK_COMMON_MASK_SH_LIST_DCN42(mask_sh)
+
 #define CLK_REG_FIELD_LIST(type) \
 	type DPREFCLK_SRC_SEL; \
 	type DENTIST_DPREFCLK_WDIVIDER; \
@@ -406,6 +427,7 @@ struct clk_mgr_registers {
 	uint32_t CLK6_spll_field_8;
 	CLK42_REG_LIST(8, uint32_t)
 	CLK42_REG_LIST(5, uint32_t)
+	uint32_t CLK8_CLK0_ALLOW_DS;
 };
 
 struct clk_mgr_shift {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/cursor_reg_cache.h b/drivers/gpu/drm/amd/display/dc/inc/hw/cursor_reg_cache.h
index 7ce2f417f86a..3932a4f766e2 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/cursor_reg_cache.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/cursor_reg_cache.h
@@ -59,7 +59,8 @@ struct cursor_attribute_cache_hubp {
 		struct {
 			uint32_t              dst_y_offset: 8;
 			uint32_t          chunk_hdl_adjust: 2;
-			uint32_t                  reserved: 22;
+			uint32_t force_cursor_to_disp_pref: 1;
+			uint32_t                  reserved: 21;
 		} bits;
 		uint32_t raw;
 	} settings;
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
index 39215ecb480e..b31b144d2e8f 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
@@ -375,6 +375,13 @@ struct dpp_funcs {
 	bool (*dpp_cm_hist_read)(
 		struct dpp *dpp_base,
 		struct cm_hist *cm_hist);
+	void (*dpp_set_pregam_state)(
+			struct dpp *dpp_base,
+			enum dc_transfer_func_predefined tr,
+			enum dc_scaling_linearity scaling);
+	void (*dpp_program_upsp)(
+			struct dpp *dpp_base,
+			const struct dscl_prog_data *dscl_prog_data);
 };
 
 
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
index e7727ed3300c..70545df981ef 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
@@ -52,6 +52,7 @@ struct encoder_init_data {
 	enum engine_id analog_engine;
 	struct dc_context *ctx;
 	enum transmitter transmitter;
+	bool hpd_active_high;
 };
 
 struct encoder_feature_support {
@@ -106,6 +107,7 @@ struct link_encoder {
 	enum hpd_source_id hpd_source;
 	bool usbc_combo_phy;
 	uint8_t txffe_state;
+	bool hpd_active_high;
 };
 
 struct link_enc_state {
@@ -242,6 +244,10 @@ struct link_encoder_funcs {
 		uint8_t digmode);
 	bool (*get_hpd_state)(struct link_encoder *enc);
 	bool (*program_hpd_filter)(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms);
+
+	void (*setup_ri_pj_check_in_sw_or_hw_mode)(struct link_encoder *link_enc,
+		unsigned char aux_or_ddc_instance,
+		bool ri_pj_sw_mode);
 };
 
 /*
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
index 30990355985d..d67373ec8e36 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
@@ -164,6 +164,7 @@ struct scaler_data {
 	struct line_buffer_params lb_params;
 	// Below struct holds the scaler values to program hw registers
 	struct dscl_prog_data dscl_prog_data;
+	enum upsp_mode upsp;
 };
 
 struct transform_funcs {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h
index d3171e70e07c..8e21aaac06b3 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
@@ -123,6 +123,8 @@ void resource_build_test_pattern_params(
 		struct resource_context *res_ctx,
 		struct pipe_ctx *pipe_ctx);
 
+enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format);
+
 bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx);
 
 enum dc_status resource_build_scaling_params_for_context(
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
index 4f18b668340c..22ad6a743038 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -336,6 +336,34 @@ static void query_dp_dual_mode_adaptor(
 	sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK;
 
 	/* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/
+	if (link->force_to_use_aux) {
+
+		if (!dm_helpers_submit_i2c_over_aux(
+			ddc,
+			DP_HDMI_DONGLE_ADDRESS,
+			0,
+			type2_dongle_buf,
+			sizeof(type2_dongle_buf),
+			true)) {
+
+			/* Use same approach as below with native i2c - HDMI dongles can sometimes fail here without retrying*/
+			while (retry_count > 0) {
+				if (dm_helpers_submit_i2c_over_aux(
+					ddc,
+					DP_HDMI_DONGLE_ADDRESS,
+					0,
+					type2_dongle_buf,
+					sizeof(type2_dongle_buf),
+					true))
+					break;
+				retry_count--;
+			}
+			/* In case I2C over Aux no response, it is interpreted as DISPLAY_DONGLE_NONE */
+			if (retry_count == 0) {
+				return;
+			}
+		}
+	} else {
 	if (!i2c_read(
 		ddc,
 		DP_HDMI_DONGLE_ADDRESS,
@@ -360,6 +388,7 @@ static void query_dp_dual_mode_adaptor(
 			return;
 		}
 	}
+	}
 
 	/* Check if Type 2 dongle.*/
 	if (type2_dongle_buf[DP_ADAPTOR_TYPE2_REG_ID] == DP_ADAPTOR_TYPE2_ID)
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_factory.c b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
index 67ce8d95bbd6..89265b083935 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
@@ -577,6 +577,10 @@ static bool construct_phy(struct dc_link *link,
 		link->is_internal_display = (disp_connect_caps_info.INTERNAL_DISPLAY != 0);
 		DC_LOG_DC("BIOS object table - is_internal_display: %d", link->is_internal_display);
 		link->no_ddc_pin = disp_connect_caps_info.NO_DDC_PIN != 0;
+		//reworked DP port on N-1 board, for testing on N-1, to be removed when IFWI ready
+		if (link->dc->config.dp_connector_no_native_i2c &&
+			(link->link_id.enum_id == link->dc->config.link_index_with_no_ddc))
+			link->no_ddc_pin = true;
 		link->force_to_use_aux = link->dc->config.dp_connector_no_native_i2c
 				&& link->no_ddc_pin;
 	}
@@ -642,6 +646,7 @@ static bool construct_phy(struct dc_link *link,
 			link->hpd_src = hpd_info.hpd_int_gpio_uid - 1;
 			link->irq_source_hpd =  DC_IRQ_SOURCE_HPD1 + link->hpd_src;
 			enc_init_data.hpd_source = link->hpd_src;
+			enc_init_data.hpd_active_high = (hpd_info.hpd_active == 0) ? true : false;
 			DC_LOG_DC("BIOS object table - hpd_int_gpio_uid id: %d", hpd_info.hpd_int_gpio_uid);
 		} else {
 			ASSERT(0);
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
index f9d5a2441e38..6123b10977bf 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_ddc.c
@@ -423,6 +423,14 @@ int link_aux_transfer_raw(struct ddc_service *ddc,
 		struct aux_payload *payload,
 		enum aux_return_code_type *operation_result)
 {
+	if (ddc->ctx->dc->config.dp_connector_no_native_i2c && ddc->link->no_ddc_pin) {
+		/* Check whether aux to be processed via dmub or dcn directly */
+		if (ddc->ctx->dc->debug.enable_dmub_aux_for_legacy_ddc) {
+			return dce_aux_transfer_dmub_raw(ddc, payload, operation_result);
+		} else {
+			return dce_aux_transfer_raw_without_ddc_pin(ddc, payload, operation_result);
+		}
+	}
 	return dce_aux_transfer_raw(ddc, payload, operation_result);
 }
 
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
index 2afdfc113675..75ec3b701d81 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
@@ -144,6 +144,11 @@ void hdmi_frl_retrieve_link_cap(struct dc_link *link, struct dc_sink *sink)
 
 	if (link->link_enc->features.flags.bits.IS_FRL_12G_CAPABLE)
 		encoder_link_rate = HDMI_FRL_LINK_RATE_12GBPS;
+	if (link->link_enc->features.flags.bits.IS_FRL_16G_CAPABLE)
+		encoder_link_rate = HDMI_FRL_LINK_RATE_16GBPS;
+
+	if (link->link_enc->features.flags.bits.IS_FRL_20G_CAPABLE)
+		encoder_link_rate = HDMI_FRL_LINK_RATE_20GBPS;
 
 	if (link->dc->debug.max_frl_rate != 0 && encoder_link_rate > link->dc->debug.max_frl_rate)
 		encoder_link_rate = link->dc->debug.max_frl_rate;
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
index a3431ec2f058..4370d64259e7 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c
@@ -40,8 +40,8 @@
  * 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)
+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);
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
index d652358eea22..758cddd9e64f 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h
@@ -395,4 +395,6 @@ void optc42_clear_optc_underflow(struct timing_generator *optc);
 bool optc42_is_optc_underflow_occurred(struct timing_generator *optc);
 bool optc42_disable_crtc(struct timing_generator *optc);
 void optc42_lock_doublebuffer_enable(struct timing_generator *optc);
+bool optc42_get_crc(struct timing_generator *optc, uint8_t idx,
+	uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb);
 #endif /* __DC_OPTC_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c
index db1b6a1b92e8..37974c45b44a 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c
@@ -1419,6 +1419,7 @@ static bool dcn10_resource_construct(
 	dc->caps.color.dpp.post_csc = 0;
 	dc->caps.color.dpp.gamma_corr = 0;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 1;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 1; // RGAM on DCN1
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
index 95abc4c38eae..996fce26941f 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
@@ -2502,6 +2502,7 @@ static bool dcn20_resource_construct(
 	dc->caps.color.dpp.post_csc = 0;
 	dc->caps.color.dpp.gamma_corr = 0;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 1;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
index 02b7dc07ad53..765c63513a31 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c
@@ -1165,6 +1165,7 @@ static bool dcn201_resource_construct(
 	dc->caps.color.dpp.post_csc = 0;
 	dc->caps.color.dpp.gamma_corr = 0;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 1;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
index b653f951e104..4095a850ebc6 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c
@@ -1478,6 +1478,7 @@ static bool dcn21_resource_construct(
 	dc->caps.color.dpp.post_csc = 0;
 	dc->caps.color.dpp.gamma_corr = 0;
 	dc->caps.color.dpp.dgam_rom_for_yuv = 1;
+	dc->caps.color.dpp.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
index 40fc66e64c1b..f09bbb932150 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
@@ -2496,6 +2496,7 @@ static bool dcn30_resource_construct(
 	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.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c
index 551565ae9ef2..29113f518c53 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c
@@ -1497,6 +1497,7 @@ static bool dcn301_resource_construct(
 	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.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
index 2574e706631d..d6b036e3933e 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
@@ -1397,6 +1397,7 @@ static bool dcn302_resource_construct(
 	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.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
index 8b24628e3e14..c8598ba23dd0 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
@@ -1341,6 +1341,7 @@ static bool dcn303_resource_construct(
 	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.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
index 372e05487847..5f08fb136b14 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
@@ -2032,6 +2032,7 @@ static bool dcn314_resource_construct(
 	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.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
index 6e112ef0a49a..7c78f8ba40ef 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
@@ -2076,6 +2076,7 @@ static bool dcn315_resource_construct(
 	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.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 1;
 	dc->caps.color.dpp.ogam_ram = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
index cd9d2087d14e..a20ff9f0c3f8 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
@@ -2428,6 +2428,7 @@ static bool dcn32_resource_construct(
 	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.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;  // no OGAM in DPP since DCN1
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
index ff9c1379896e..105fba8ff171 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
@@ -1919,6 +1919,7 @@ static bool dcn321_resource_construct(
 	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.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
index 1b9b6eb8b322..a92e0dc5ad6a 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
@@ -2058,6 +2058,7 @@ static bool dcn35_resource_construct(
 	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.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;  // no OGAM in DPP since DCN1
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
index 2268ced16969..68a2169da0c1 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
@@ -2031,6 +2031,7 @@ static bool dcn351_resource_construct(
 	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.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;  // no OGAM in DPP since DCN1
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
index b1323e76801e..ba04e8b9b569 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
@@ -2028,6 +2028,7 @@ static bool dcn36_resource_construct(
 	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.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;  // no OGAM in DPP since DCN1
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
index 181cb7135dfb..fff84f9ce816 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
@@ -305,19 +305,21 @@ static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5];
 
 static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5];
 
-#define link_regs_init(id, phyid)\
-	LE_DCN401_REG_LIST_RI(id)
+#define link_regs_init(id, phyid) \
+	LE_DCN401_REG_LIST_RI(id), \
+	LE_DCN60_REG_LIST_RI(id)
 
 static struct dcn10_link_enc_registers link_enc_regs[4];
 
 
 static const struct dcn10_link_enc_shift le_shift = {
-	LINK_ENCODER_MASK_SH_LIST_DCN401(__SHIFT)
+	LINK_ENCODER_MASK_SH_LIST_DCN401(__SHIFT), \
+	LINK_ENCODER_MASK_SH_LIST_DCN60_ON_DCN401(__SHIFT)
 };
 
-
 static const struct dcn10_link_enc_mask le_mask = {
-	LINK_ENCODER_MASK_SH_LIST_DCN401(_MASK)
+	LINK_ENCODER_MASK_SH_LIST_DCN401(_MASK), \
+	LINK_ENCODER_MASK_SH_LIST_DCN60_ON_DCN401(_MASK)
 };
 
 
@@ -602,8 +604,12 @@ static const struct dccg_mask dccg_mask = {
 
 static struct dce_hwseq_registers hwseq_reg;
 
-#define hwseq_reg_init()\
-	HWSEQ_DCN401_REG_LIST()
+#define HWSEQ_DCN60_REG_LIST() \
+	SR(HDCP_INTERRUPT_DEST)
+
+#define hwseq_reg_init() \
+	HWSEQ_DCN401_REG_LIST(), \
+	HWSEQ_DCN60_REG_LIST()
 
 #define HWSEQ_DCN401_MASK_SH_LIST(mask_sh)\
 	HWSEQ_DCN_MASK_SH_LIST(mask_sh), \
@@ -651,12 +657,20 @@ static struct dce_hwseq_registers hwseq_reg;
 	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)
 
+#define HWSEQ_DCN60_MASK_SH_LIST(mask_sh) \
+	HWS_SF(, HDCP_INTERRUPT_DEST, DOUT_IHC_HDCP0_I2C_XFER_REQ_INTERRUPT_DEST, mask_sh), \
+	HWS_SF(, HDCP_INTERRUPT_DEST, DOUT_IHC_HDCP1_I2C_XFER_REQ_INTERRUPT_DEST, mask_sh), \
+	HWS_SF(, HDCP_INTERRUPT_DEST, DOUT_IHC_HDCP2_I2C_XFER_REQ_INTERRUPT_DEST, mask_sh), \
+	HWS_SF(, HDCP_INTERRUPT_DEST, DOUT_IHC_HDCP3_I2C_XFER_REQ_INTERRUPT_DEST, mask_sh)
+
 static const struct dce_hwseq_shift hwseq_shift = {
-		HWSEQ_DCN401_MASK_SH_LIST(__SHIFT)
+		HWSEQ_DCN401_MASK_SH_LIST(__SHIFT), \
+		HWSEQ_DCN60_MASK_SH_LIST(__SHIFT)
 };
 
 static const struct dce_hwseq_mask hwseq_mask = {
-		HWSEQ_DCN401_MASK_SH_LIST(_MASK)
+		HWSEQ_DCN401_MASK_SH_LIST(_MASK), \
+		HWSEQ_DCN60_MASK_SH_LIST(_MASK)
 };
 
 #define vmid_regs_init(id)\
@@ -2111,6 +2125,7 @@ static bool dcn401_resource_construct(
 	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.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
index 42a0986d6fe2..8e3473f86490 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
@@ -236,6 +236,10 @@ int dcn401_get_power_profile(const struct dc_state *context);
 	SRI_ARR(DIG_BE_CLK_CNTL, DIG, id),\
 	SR_ARR(DIO_CLK_CNTL, id)
 
+#define LE_DCN60_REG_LIST_RI(id)                                             \
+	SRI_ARR(HDCP_I2C_CONTROL_0, DIG, id),                                    \
+	SRI_ARR(HDCP_INT_CONTROL, DIG, id)
+
 /* DPP */
 #define DPP_REG_LIST_DCN401_COMMON_RI(id)                                    \
 	SRI_ARR(CM_DEALPHA, CM, id), SRI_ARR(CM_MEM_PWR_STATUS, CM, id),         \
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
index dba1b69137f9..7507994f12d8 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
@@ -2066,6 +2066,7 @@ static bool dcn42_resource_construct(
 	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.upsp_pre_scaler = 0;
 
 	dc->caps.color.dpp.hw_3d_lut = 0;
 	dc->caps.color.dpp.ogam_ram = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c
index 1e3ee25732fa..3821846aa2d0 100644
--- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c
+++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c
@@ -6,6 +6,7 @@
 #include "soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.h"
 #include "soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.h"
 #include "soc_and_ip_translator/dcn42b/dcn42b_soc_and_ip_translator.h"
+#include "soc_and_ip_translator/dcn60/dcn60_soc_and_ip_translator.h"
 
 static void dc_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc_and_ip_translator,
 		enum dce_version dc_version)
@@ -20,6 +21,9 @@ static void dc_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc
 	case DCN_VERSION_4_2B:
 		dcn42b_construct_soc_and_ip_translator(soc_and_ip_translator);
 		break;
+	case DCN_VERSION_6_0:
+		dcn60_construct_soc_and_ip_translator(soc_and_ip_translator);
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
index 94d4b40ee16a..d8a18cd97811 100644
--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
@@ -122,6 +122,8 @@ enum dmub_asic {
 	DMUB_ASIC_DCN401,
 	DMUB_ASIC_DCN42,
 	DMUB_ASIC_DCN42B,
+	DMUB_ASIC_DCN60,
+
 	DMUB_ASIC_MAX,
 };
 
@@ -318,6 +320,8 @@ struct dmub_srv_fb_info {
 struct dmub_soc_fb_info {
 	uint64_t fb_base;
 	uint64_t fb_offset;
+	uint32_t alt_channel_region_size[2];
+	uint64_t alt_channel_region_base[2]; /* mc address */
 };
 
 /*
@@ -608,6 +612,7 @@ struct dmub_srv {
 	struct dmub_srv_dcn35_regs *regs_dcn35;
 	const struct dmub_srv_dcn401_regs *regs_dcn401;
 	struct dmub_srv_dcn42_regs *regs_dcn42;
+    const struct dmub_srv_dcn60_regs *regs_dcn60;
 	struct dmub_srv_base_funcs funcs;
 	struct dmub_srv_hw_funcs hw_funcs;
 	struct dmub_srv_inbox inbox1;
diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
index e7879bd81f83..44aefa3608ec 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -910,6 +910,41 @@ struct dmub_cursor_offload_pipe_data_dcn401_v1 {
 	uint32_t reserved2[3];
 };
 
+/**
+ * struct dmub_cursor_offload_pipe_data_dcn60_v1 - DCN60 per pipe data.
+ */
+struct dmub_cursor_offload_pipe_data_dcn60_v1 {
+	uint32_t CURSOR0_0_CURSOR_SURFACE_ADDRESS;
+	uint32_t CURSOR0_0_CURSOR_SURFACE_ADDRESS_HIGH;
+	uint32_t CURSOR0_0_CURSOR_SIZE__CURSOR_WIDTH : 16;
+	uint32_t CURSOR0_0_CURSOR_SIZE__CURSOR_HEIGHT : 16;
+	uint32_t CURSOR0_0_CURSOR_POSITION__CURSOR_X_POSITION : 16;
+	uint32_t CURSOR0_0_CURSOR_POSITION__CURSOR_Y_POSITION : 16;
+	uint32_t CURSOR0_0_CURSOR_HOT_SPOT__CURSOR_HOT_SPOT_X : 16;
+	uint32_t CURSOR0_0_CURSOR_HOT_SPOT__CURSOR_HOT_SPOT_Y : 16;
+	uint32_t CURSOR0_0_CURSOR_DST_OFFSET__CURSOR_DST_X_OFFSET : 13;
+	uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_ENABLE : 1;
+	uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_MODE : 3;
+	uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_2X_MAGNIFY : 1;
+	uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_PITCH : 2;
+	uint32_t CURSOR0_0_CURSOR_CONTROL__CURSOR_LINES_PER_CHUNK : 5;
+	uint32_t reserved0[4];
+	uint32_t CM_CUR0_CURSOR0_CONTROL__CUR0_ENABLE : 1;
+	uint32_t CM_CUR0_CURSOR0_CONTROL__CUR0_MODE : 3;
+	uint32_t CM_CUR0_CURSOR0_CONTROL__CUR0_EXPANSION_MODE : 1;
+	uint32_t CM_CUR0_CURSOR0_CONTROL__CUR0_ROM_EN : 1;
+	uint32_t CM_CUR0_CURSOR0_COLOR0__CUR0_COLOR0 : 24;
+	uint32_t CM_CUR0_CURSOR0_COLOR1__CUR0_COLOR1 : 24;
+	uint32_t CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y__CUR0_FP_BIAS_G_Y : 16;
+	uint32_t CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y__CUR0_FP_SCALE_G_Y, : 16;
+	uint32_t CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB__CUR0_FP_BIAS_RB_CRCB : 16;
+	uint32_t CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB__CUR0_FP_SCALE_RB_CRCB : 16;
+	uint32_t reserved1[4];
+	uint32_t HUBPREQ0_CURSOR_SETTINGS__CURSOR0_DST_Y_OFFSET : 8;
+	uint32_t HUBPREQ0_CURSOR_SETTINGS__CURSOR0_CHUNK_HDL_ADJUST : 8;
+	uint32_t HUBPREQ0_CURSOR_SETTINGS__FORCE_CURSOR_TO_DISP_PREF : 1;
+	uint32_t reserved2[3];
+};
 /**
  * struct dmub_cursor_offload_pipe_data_v1 - Per pipe data for cursor offload.
  */
@@ -917,6 +952,7 @@ struct dmub_cursor_offload_pipe_data_v1 {
 	union {
 		struct dmub_cursor_offload_pipe_data_dcn30_v1 dcn30; /**< DCN30 cursor data. */
 		struct dmub_cursor_offload_pipe_data_dcn401_v1 dcn401; /**< DCN401 cursor data. */
+		struct dmub_cursor_offload_pipe_data_dcn60_v1 dcn60; /**< DCN60 cursor data. */
 		uint8_t payload[96]; /**< Guarantees the cursor pipe data size per-pipe. */
 	};
 };
@@ -2465,6 +2501,7 @@ enum fams2_stream_type {
 	FAMS2_STREAM_TYPE_VACTIVE = 2,
 	FAMS2_STREAM_TYPE_DRR = 3,
 	FAMS2_STREAM_TYPE_SUBVP = 4,
+	FAMS2_STREAM_TYPE_ALTERNATE = 5,
 };
 
 struct dmub_rect16 {
@@ -2489,6 +2526,140 @@ struct dmub_rect16 {
 	uint16_t height;
 };
 
+struct plane_pipe_rect {
+	struct dmub_rect16 luma;
+	struct dmub_rect16 chroma;
+};
+
+/**
+ * Structure to hold the LSDMA source / dest copy parameters.
+ * Each field is an array of [2][4]:
+ * [2] - Instance 0 is the copy for current frame, instance 1 is the copy for next frame (instance 1 potentially unused if no next)
+ * [4] - One instance per pipe
+ */
+
+struct lsdma_outputs {
+	uint16_t src_x[2][4]; // src x position for the copy. Array of [2][4] for curr vs. next and each pipe
+	uint16_t src_y[2][4]; // src y position for the copy
+	uint16_t dst_x[2][4]; // dst x position for the copy (can change for curr vs. next)
+	uint16_t dst_y[2][4]; // dst y position for the copy (can change for curr vs. next)
+	uint16_t width[2][4]; // src and dst width for the copy (src and dst must match)
+	uint16_t height[2][4]; // src and dst height for the copy (src and dst must match)
+	uint16_t dst_pitch[4]; // dst pitch for the copy (same for curr and next)
+};
+
+struct dmub_fams2_alternate_stream_dynamic_state {
+	uint64_t earliest_init_tick; // track earliest possible init tick for calculating is_tick_in_allow
+	uint32_t otg_frame_pending_clear[3]; // In this context pending means prefetch has never been completed for this frame yet
+	uint8_t flip_pending_clear_order[3];
+	uint8_t num_pending_flips;
+	uint32_t prefetch_start_line_x1000[3]; // can compute from existing params, but store because we use this multiple times
+	uint16_t prefetch_end_line[3]; // can compute from existing params, but store because we use this multiple times
+	uint16_t recout_y[3];
+	uint8_t flip_pending[3];
+	uint8_t copy_from_earliest[3];
+	uint16_t lsdma_bandwidth_mbps;
+	uint16_t vstartup_line;
+	uint16_t vready_line;
+	uint8_t cursor_size[3]; //  Cursor array per plane for now - if we assume a single cursor, then we don't need an array
+	uint8_t pad; // to maintain alignment for below fields - re-arrange structure once all fields are finalized
+	/* outputs: */
+	uint16_t subvp_start_line_a[3];
+	uint16_t subvp_height_a[3];
+	uint16_t subvp_next_start_line_a[3];
+	uint16_t subvp_next_height_a[3];
+	uint16_t subvp_start_line_b[3];
+	uint16_t subvp_height_b[3];
+	uint16_t subvp_next_start_line_b[3];
+	uint16_t subvp_next_height_b[3];
+	uint16_t subvp_c_start_line_a[3];
+	uint16_t subvp_c_height_a[3];
+	uint16_t subvp_c_next_start_line_a[3];
+	uint16_t subvp_c_next_height_a[3];
+	uint16_t subvp_c_start_line_b[3];
+	uint16_t subvp_c_height_b[3];
+	uint16_t subvp_c_next_start_line_b[3];
+	uint16_t subvp_c_next_height_b[3];
+	uint8_t subvp_position[3];
+	uint8_t pad1[1]; // to maintain alignment for below fields - re-arrange structure once all fields are finalized
+	uint32_t program_go_line;
+	uint32_t program_go_frame_count;
+	uint16_t svp0_start_dst_line;
+	uint16_t svp0_end_dst_line;
+	uint16_t svp1_start_dst_line;
+	uint16_t svp1_end_dst_line;
+	struct lsdma_outputs lsdma[2]; // [2] - instance per SVP0 and SVP1
+	struct lsdma_outputs lsdma_c[2]; // [2] - instance per SVP0 and SVP1
+};
+struct dmub_fams2_cmd_alternate_stream_static_state {
+	uint32_t total_bytes_to_copy;
+	uint16_t svp0_dst_lines; // per stream
+	uint16_t svp1_dst_lines; // per stream
+	uint16_t min_lead_dst_lines; // per stream, should be max(nominal_req_limit, vstartup_to_vactive). Does not have to be maxed over all planes
+	uint16_t svp_req_limit; // per stream, should be the same value in time between all streams max(2 swaths, dst_y_pre) over all planes
+	uint16_t fw_delays;
+	uint16_t vstartup_start;
+	uint16_t rec_height[3];
+	uint16_t viewport_start[3];
+	uint16_t viewport_size[3]; // for now size will be the number of lines perpendicular to scan direction (height for 0 / 180, width for 90 and 270)
+	uint16_t viewport_start_c[3];
+	uint16_t viewport_size_c[3];
+	uint16_t surface_pitch[3];
+	uint16_t surface_pitch_c[3];
+	uint16_t surface_height[3];
+	uint16_t surface_height_c[3];
+	uint8_t element_size[3];
+	uint8_t element_size_c[3];
+	uint8_t swizzle_mode[3]; // TODO: Add mapping, should be value used in LSDMA command
+	uint8_t vready_offset_lines; // vready offset from vstartup in lines (rounded up, as the actual offset may be a fraction of a line)
+	uint16_t dst_y_prefetch_x1000[3];
+	uint16_t total_swaths[3];
+	uint16_t total_swaths_c[3];
+	uint8_t prefetch_swaths[3];
+	uint8_t prefetch_swaths_c[3];
+	uint8_t swath_height[3];
+	uint8_t swath_height_c[3];
+	uint16_t block_256b_width[3];
+	uint16_t block_256b_height[3];
+	uint16_t block_256b_width_c[3];
+	uint16_t block_256b_height_c[3];
+	uint16_t macro_tile_width[3];
+	uint16_t macro_tile_width_c[3];
+	union {
+		struct {
+			uint8_t is_multi_planar : 1;
+			uint8_t is_yuv420 : 1;
+			uint8_t prefetch_relative_vblank : 1;
+			uint8_t vertical_access : 1; // vertical_access = 1 means 90 or 270 rotation
+			uint8_t access_direction : 1; // access_direction = 1 means bigger to smaller coordinations (e.g., scan from 2160 to 0 as opposed to regular 0 to 2160)
+			uint8_t dcc : 1;
+			uint8_t tmz : 1; // TODO: Need to assign outside of DML (DML not aware of TMZ)
+		} bits;
+		uint8_t all;
+	} config[3];
+	uint8_t max_cursor_size;
+	uint16_t pre_hdl_delta_x1000[3];
+	uint16_t pre_hdl_delta_c_x1000[3];
+	uint16_t rec_hdl_delta_x1000[3];
+	uint16_t rec_hdl_delta_c_x1000[3];
+	uint16_t dst_y_per_vm_vblank_x1000[3];
+	uint16_t dst_y_per_row_vblank_x1000[3];
+	uint16_t dst_y_after_scaler[3];
+	uint16_t vinit_prefill[3];
+	uint16_t vinit_prefill_c[3];
+	uint16_t vratio_x1000[3];
+	uint16_t vratio_c_x1000[3];
+	struct plane_pipe_rect pipe_viewports[4];
+	/* TODO - remove these deprecated vars */
+	uint32_t pipe_copy_offset[2][4]; // [2] - SVP0/1, [4] - 4 pipes
+	uint32_t pipe_copy_offset_c[2][4];
+	/* bits 47:16 of the surface address */
+	uint32_t pipe_copy_addr_47_16[2][4]; // [2] - SVP0/1, [4] - 4 pipes
+	uint32_t pipe_copy_addr_47_16_c[2][4];
+	uint32_t pipe_copy_max_size[2][4];
+	uint32_t pipe_copy_max_size_c[2][4];
+};
+
 /* static stream state */
 struct dmub_fams2_legacy_stream_static_state {
 	uint8_t vactive_det_fill_delay_otg_vlines;
@@ -2567,6 +2738,7 @@ union dmub_fams2_cmd_stream_static_sub_state {
 
 union dmub_fams2_stream_static_sub_state_v2 {
 	COMMON_STREAM_STATIC_SUB_STATE
+	struct dmub_fams2_cmd_alternate_stream_static_state alternate;
 }; //v2
 
 struct dmub_fams2_stream_static_state {
@@ -2660,7 +2832,8 @@ union dmub_fams2_global_feature_config {
 		uint32_t enable_visual_confirm: 1;
 		uint32_t allow_delay_check_mode: 2;
 		uint32_t legacy_method_no_fams2 : 1;
-		uint32_t reserved : 23;
+		uint32_t alternate_channel_workaround : 1;
+		uint32_t reserved: 22;
 	} bits;
 	uint32_t all;
 };
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
index 5a1a2276c432..204375f1eff8 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
@@ -42,6 +42,7 @@
 #include "dmub_dcn401.h"
 #include "dmub_dcn42.h"
 #include "dmub_dcn42b.h"
+#include "dmub_dcn60.h"
 #include "os_types.h"
 /*
  * Note: the DMUB service is standalone. No additional headers should be
@@ -528,6 +529,57 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
 		funcs->enable_reg_inbox0_rsp_int = dmub_dcn401_enable_reg_inbox0_rsp_int;
 		funcs->enable_reg_outbox0_rdy_int = dmub_dcn401_enable_reg_outbox0_rdy_int;
 		break;
+	case DMUB_ASIC_DCN60:
+		dmub->regs_dcn60 = &dmub_srv_dcn60_regs;
+		funcs->configure_dmub_in_system_memory = dmub_dcn60_configure_dmub_in_system_memory;
+		funcs->send_inbox0_cmd = dmub_dcn60_send_inbox0_cmd;
+		funcs->clear_inbox0_ack_register = dmub_dcn60_clear_inbox0_ack_register;
+		funcs->read_inbox0_ack_register = dmub_dcn60_read_inbox0_ack_register;
+		funcs->reset = dmub_dcn60_reset;
+		funcs->reset_release = dmub_dcn60_reset_release;
+		funcs->backdoor_load = dmub_dcn60_backdoor_load;
+		funcs->backdoor_load_zfb_mode = dmub_dcn60_backdoor_load_zfb_mode;
+		funcs->setup_windows = dmub_dcn60_setup_windows;
+		funcs->setup_mailbox = dmub_dcn60_setup_mailbox;
+		funcs->get_inbox1_wptr = dmub_dcn60_get_inbox1_wptr;
+		funcs->get_inbox1_rptr = dmub_dcn60_get_inbox1_rptr;
+		funcs->set_inbox1_wptr = dmub_dcn60_set_inbox1_wptr;
+		funcs->setup_out_mailbox = dmub_dcn60_setup_out_mailbox;
+		funcs->get_outbox1_wptr = dmub_dcn60_get_outbox1_wptr;
+		funcs->set_outbox1_rptr = dmub_dcn60_set_outbox1_rptr;
+		funcs->is_supported = dmub_dcn60_is_supported;
+		funcs->is_hw_init = dmub_dcn60_is_hw_init;
+		funcs->set_gpint = dmub_dcn60_set_gpint;
+		funcs->is_gpint_acked = dmub_dcn60_is_gpint_acked;
+		funcs->get_gpint_response = dmub_dcn60_get_gpint_response;
+		funcs->get_gpint_dataout = dmub_dcn60_get_gpint_dataout;
+		funcs->get_fw_status = dmub_dcn60_get_fw_boot_status;
+		funcs->enable_dmub_boot_options = dmub_dcn60_enable_dmub_boot_options;
+		funcs->skip_dmub_panel_power_sequence = dmub_dcn60_skip_dmub_panel_power_sequence;
+		//outbox0 call stacks
+		funcs->setup_outbox0 = dmub_dcn60_setup_outbox0;
+		funcs->get_outbox0_wptr = dmub_dcn60_get_outbox0_wptr;
+		funcs->set_outbox0_rptr = dmub_dcn60_set_outbox0_rptr;
+
+		funcs->get_current_time = dmub_dcn60_get_current_time;
+		funcs->get_diagnostic_data = dmub_dcn60_get_diagnostic_data;
+
+		funcs->send_reg_inbox0_cmd_msg = dmub_dcn60_send_reg_inbox0_cmd_msg;
+		funcs->read_reg_inbox0_rsp_int_status = dmub_dcn60_read_reg_inbox0_rsp_int_status;
+		funcs->read_reg_inbox0_cmd_rsp = dmub_dcn60_read_reg_inbox0_cmd_rsp;
+		funcs->write_reg_inbox0_rsp_int_ack = dmub_dcn60_write_reg_inbox0_rsp_int_ack;
+		funcs->clear_reg_inbox0_rsp_int_ack = dmub_dcn60_clear_reg_inbox0_rsp_int_ack;
+		funcs->enable_reg_inbox0_rsp_int = dmub_dcn60_enable_reg_inbox0_rsp_int;
+		default_inbox_type = DMUB_CMD_INTERFACE_FB; // still default to FB for now
+
+		funcs->write_reg_outbox0_rdy_int_ack = dmub_dcn60_write_reg_outbox0_rdy_int_ack;
+		funcs->read_reg_outbox0_msg = dmub_dcn60_read_reg_outbox0_msg;
+		funcs->write_reg_outbox0_rsp = dmub_dcn60_write_reg_outbox0_rsp;
+		funcs->read_reg_outbox0_rdy_int_status = dmub_dcn60_read_reg_outbox0_rdy_int_status;
+		funcs->read_reg_outbox0_rsp_int_status = dmub_dcn60_read_reg_outbox0_rsp_int_status;
+		funcs->enable_reg_inbox0_rsp_int = dmub_dcn60_enable_reg_inbox0_rsp_int;
+		funcs->enable_reg_outbox0_rdy_int = dmub_dcn60_enable_reg_outbox0_rdy_int;
+		break;
 	default:
 		return false;
 	}
diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h
index ca77d29ebacc..7ed785be8473 100644
--- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h
+++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h
@@ -266,6 +266,24 @@ enum {
 #define ASICREV_IS_DCN36(eChipRev) ((eChipRev) >= 0x50 && (eChipRev) < 0xC0)
 
 #define AMDGPU_FAMILY_GC_12_0_0         152 /* GC 12.0.0 */
+#define AMDGPU_FAMILY_GC_13_0_1         153 /*We may need an update if we find DCN5 and DCN6
+											do not share the same GFX version*/
+enum {
+	DCN6_VARIANT0_A0        = 0x1,
+	DCN6_VARIANT1_A0        = DCN6_VARIANT0_A0,
+	DCN6_VARIANT2_A0        = 0x10,
+	DCN6_VARIANT2_B0        = 0x11,
+	DCN6_VARIANT3_A0        = 0x20,
+	DCN6_VARIANT3_UPPER     = 0x2F,
+	DCN6_UNKNOWN		= 0xFF
+};
+
+#define ASICREV_IS_DCN6_VARIANT0(eChipRev)        (eChipRev < DCN6_VARIANT2_A0)
+#define ASICREV_IS_DCN6_VARIANT1(eChipRev)        ASICREV_IS_DCN_VARIANT0(eChipRev)
+#define ASICREV_IS_DCN6_VARIANT2(eChipRev)        (eChipRev >= DCN6_VARIANT2_A0 && eChipRev < DCN6_VARIANT3_A0)
+#define ASICREV_IS_DCN6_VARIANT2_A0(eChipRev)     (eChipRev >= DCN6_VARIANT2_A0 && eChipRev < DCN6_VARIANT2_B0)
+#define ASICREV_IS_DCN6_VARIANT2_B0(eChipRev)     (eChipRev >= DCN6_VARIANT2_B0 && eChipRev < DCN6_VARIANT3_A0)
+#define ASICREV_IS_DCN6_VARIANT3(eChipRev)        (eChipRev >= DCN6_VARIANT3_A0 && eChipRev <= DCN6_VARIANT3_UPPER)
 
 enum {
 	GC_12_0_0_A0 = 0x50,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 05/41] drm/amd/display: Enable DCN6 sources compilation
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
  2026-07-31 21:12 ` [PATCH 03/41] drm/amd/display: Enable DCN6 init Roman.Li
  2026-07-31 21:12 ` [PATCH 04/41] drm/amd/display: Dependent changes for DCN6 Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 06/41] drm/amd/display: Remove duplicate in tests/Makefile Roman.Li
                   ` (36 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Roman Li

From: Aurabindo Pillai <aurabindo.pillai@amd.com>

Update the Makefiles so that DCN6 related newly added sources are compiled

Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: Roman Li <Roman.Li@amd.com>
Reviewed-by: Ivan Lipski <ivan.lipski@amd.com>
---
 .../gpu/drm/amd/display/dc/clk_mgr/Makefile   |  9 +++++++
 drivers/gpu/drm/amd/display/dc/dccg/Makefile  |  8 ++++++
 drivers/gpu/drm/amd/display/dc/dio/Makefile   |  8 ++++++
 .../gpu/drm/amd/display/dc/dml2_0/Makefile    | 25 +++++++++++++++++++
 drivers/gpu/drm/amd/display/dc/dpp/Makefile   | 17 +++++++++++++
 drivers/gpu/drm/amd/display/dc/dsc/Makefile   |  7 ++++++
 drivers/gpu/drm/amd/display/dc/gpio/Makefile  | 10 ++++++++
 drivers/gpu/drm/amd/display/dc/hpo/Makefile   |  8 ++++++
 .../gpu/drm/amd/display/dc/hubbub/Makefile    |  8 ++++++
 drivers/gpu/drm/amd/display/dc/hubp/Makefile  | 16 ++++++++++++
 drivers/gpu/drm/amd/display/dc/hwss/Makefile  | 16 ++++++++++++
 drivers/gpu/drm/amd/display/dc/irq/Makefile   |  9 +++++++
 drivers/gpu/drm/amd/display/dc/mpc/Makefile   |  8 ++++++
 drivers/gpu/drm/amd/display/dc/opp/Makefile   |  8 ++++++
 drivers/gpu/drm/amd/display/dc/optc/Makefile  |  9 +++++++
 .../gpu/drm/amd/display/dc/resource/Makefile  | 10 ++++++++
 .../display/dc/soc_and_ip_translator/Makefile |  3 +++
 drivers/gpu/drm/amd/display/dmub/src/Makefile |  1 +
 18 files changed, 180 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
index fb234a729bdc..8cfd7bf57fbe 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
@@ -195,4 +195,13 @@ AMD_DAL_CLK_MGR_DCN42B = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn42b/,$(CLK_MGR_
 
 AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN42B)
 
+
+###############################################################################
+# DCN60
+###############################################################################
+CLK_MGR_DCN60 = dcn60_clk_mgr.o dcn60_clk_mgr_smu_msg.o
+
+AMD_DAL_CLK_MGR_DCN60 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn60/,$(CLK_MGR_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN60)
 endif
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/Makefile b/drivers/gpu/drm/amd/display/dc/dccg/Makefile
index bf7e71166b5e..5a1ce0e7cd70 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dccg/Makefile
@@ -109,4 +109,12 @@ DCCG_DCN42 = dcn42_dccg.o
 AMD_DAL_DCCG_DCN42 = $(addprefix $(AMDDALPATH)/dc/dccg/dcn42/,$(DCCG_DCN42))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_DCCG_DCN42)
+###############################################################################
+# DCN60
+###############################################################################
+DCCG_DCN60 = dcn60_dccg.o
+
+AMD_DAL_DCCG_DCN60 = $(addprefix $(AMDDALPATH)/dc/dccg/dcn60/,$(DCCG_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DCCG_DCN60)
 endif
diff --git a/drivers/gpu/drm/amd/display/dc/dio/Makefile b/drivers/gpu/drm/amd/display/dc/dio/Makefile
index 4832533b9514..d6e715c37989 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dio/Makefile
@@ -132,4 +132,12 @@ DIO_DCN42 = dcn42_dio_link_encoder.o dcn42_dio_stream_encoder.o
 AMD_DAL_DIO_DCN42 = $(addprefix $(AMDDALPATH)/dc/dio/dcn42/,$(DIO_DCN42))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN42)
+###############################################################################
+# DCN60
+###############################################################################
+DIO_DCN60 = dcn60_dio_link_encoder.o dcn60_dio_stream_encoder.o
+
+AMD_DAL_DIO_DCN60 = $(addprefix $(AMDDALPATH)/dc/dio/dcn60/,$(DIO_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN60)
 endif
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
index e9ce7813b0f5..35d697872a9a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
@@ -52,6 +52,9 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/src/dml2_standalo
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/src/inc
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/inc
 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/inc/bounding_boxes/
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/src/dml2_utm_soc_bb/
+subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2_0/dml21/src/dml2_cga/
 
 # Add FPU flags to all dml2 files by default, remove NO_FPU flags.
 # FPU flags step 1: Find all .c files in dal/dc/dml2_0 and it's subfolders
@@ -107,6 +110,28 @@ DML21 += src/dml2_pmo/dml2_pmo_dcn4_fams2.o
 DML21 += src/dml2_pmo/dml2_pmo_dcn42.o
 DML21 += src/dml2_standalone_libraries/lib_float_math.o
 DML21 += src/dml2_standalone_libraries/lib_frl_cap_check.o
+DML21 += src/dml2_top/dml2_top_utm.o
+DML21 += src/dml2_core/dml2_core_dcn5_calcs_dchub.o
+DML21 += src/dml2_core/dml2_core_dcn5_calcs_display_pipe.o
+DML21 += src/dml2_core/dml2_core_dcn5_calcs_dsc_latency.o
+DML21 += src/dml2_core/dml2_core_dcn5_funcs_initialize.o
+DML21 += src/dml2_core/dml2_core_dcn5_funcs_mode_programming.o
+DML21 += src/dml2_core/dml2_core_dcn5_funcs_mode_support.o
+DML21 += src/dml2_dpmm/dml2_dpmm_dcn5.o
+DML21 += src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.o
+DML21 += src/dml2_utm_soc_bb/dml2_utm_soc_bb_factory.o
+DML21 += src/dml2_cga/dml2_cga_dcn6.o
+DML21 += src/dml2_cga/dml2_cga_factory.o
+DML21 += src/dml2_core/dml2_core_dcn6_calcs_dchub.o
+DML21 += src/dml2_core/dml2_core_dcn6_funcs_initialize.o
+DML21 += src/dml2_core/dml2_core_dcn6_funcs_mode_programming.o
+DML21 += src/dml2_core/dml2_core_dcn6_funcs_mode_support.o
+DML21 += src/dml2_pmo/dml2_pmo_dcn5.o
+DML21 += src/dml2_pmo/dml2_pmo_dcn5_stage_optimizers.o
+DML21 += src/dml2_pmo/dml2_pmo_dcn6.o
+DML21 += src/dml2_pmo/dml2_pmo_dcn6_stage_optimizers.o
+DML21 += src/dml2_standalone_libraries/alternate_pstate_shared_lib.o
+DML21 += src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.o
 DML21 += dml21_translation_helper.o
 DML21 += dml21_wrapper.o
 DML21 += dml21_wrapper_fpu.o
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/Makefile b/drivers/gpu/drm/amd/display/dc/dpp/Makefile
index 2595b2504f9d..f5da45aacfca 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dpp/Makefile
@@ -88,4 +88,21 @@ DPP_DCN42 = dcn42_dpp.o
 AMD_DAL_DPP_DCN42 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn42/,$(DPP_DCN42))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN42)
+
+###############################################################################
+
+DPP_DCN50 = dcn50_dpp.o
+
+AMD_DAL_DPP_DCN50 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn50/,$(DPP_DCN50))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN50)
+
+###############################################################################
+
+DPP_DCN60 = dcn60_dpp.o dcn60_dpp_dscl.o
+
+AMD_DAL_DPP_DCN60 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn60/,$(DPP_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN60)
+
 endif
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/Makefile b/drivers/gpu/drm/amd/display/dc/dsc/Makefile
index 94883c4e4c61..47dbc6140808 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dsc/Makefile
@@ -29,6 +29,13 @@ DSC_DCN401 += dcn401_dsc.o
 
 AMD_DISPLAY_FILES += $(addprefix $(AMDDALPATH)/dc/dsc/dcn401/,$(DSC_DCN401))
 
+###############################################################################
+# DCN60
+###############################################################################
+
+DSC_DCN60 += dcn60_dsc.o
+
+AMD_DISPLAY_FILES += $(addprefix $(AMDDALPATH)/dc/dsc/dcn60/,$(DSC_DCN60))
 endif
 
 DSC = dc_dsc.o rc_calc.o rc_calc_dpi.o
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile
index 3a860b016b7a..3deb34cd260f 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile
@@ -151,3 +151,13 @@ GPIO_DCN42B = hw_translate_dcn42b.o hw_factory_dcn42b.o
 AMD_DAL_GPIO_DCN42B = $(addprefix $(AMDDALPATH)/dc/gpio/dcn42b/,$(GPIO_DCN42B))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCN42B)
+
+###############################################################################
+# DCN 6.0
+###############################################################################
+
+GPIO_DCN60 = hw_translate_dcn60.o hw_factory_dcn60.o
+
+AMD_DAL_GPIO_DCN60 = $(addprefix $(AMDDALPATH)/dc/gpio/dcn60/,$(GPIO_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCN60)
diff --git a/drivers/gpu/drm/amd/display/dc/hpo/Makefile b/drivers/gpu/drm/amd/display/dc/hpo/Makefile
index db60564b9cfd..b5df5c569806 100644
--- a/drivers/gpu/drm/amd/display/dc/hpo/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/hpo/Makefile
@@ -66,4 +66,12 @@ HPO_DCN42 += dcn42_hpo_frl_stream_encoder.o
 AMD_DAL_HPO_DCN42 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn42/,$(HPO_DCN42))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN42)
+###############################################################################
+# DCN60
+###############################################################################
+HPO_DCN60 = dcn60_hpo_frl_stream_encoder.o dcn60_hpo_frl_link_encoder.o
+
+AMD_DAL_HPO_DCN60 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn60/,$(HPO_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN60)
 endif
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/Makefile b/drivers/gpu/drm/amd/display/dc/hubbub/Makefile
index 29c8e2651442..e20f6067977e 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/Makefile
@@ -109,4 +109,12 @@ AMD_DAL_HUBBUB_DCN42 = $(addprefix $(AMDDALPATH)/dc/hubbub/dcn42/,$(HUBBUB_DCN42
 
 AMD_DISPLAY_FILES += $(AMD_DAL_HUBBUB_DCN42)
 
+###############################################################################
+HUBBUB_DCN60 = dcn60_hubbub.o
+
+AMD_DAL_HUBBUB_DCN60 = $(addprefix $(AMDDALPATH)/dc/hubbub/dcn60/,$(HUBBUB_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_HUBBUB_DCN60)
+
+
 endif
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/Makefile b/drivers/gpu/drm/amd/display/dc/hubp/Makefile
index e0799bb873e6..6bfd302ba9c2 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/hubp/Makefile
@@ -96,10 +96,26 @@ AMD_DISPLAY_FILES += $(AMD_DAL_HUBP_DCN401)
 
 ###############################################################################
 
+HUBP_DCN50 = dcn50_hubp.o
+
+AMD_DAL_HUBP_DCN50 = $(addprefix $(AMDDALPATH)/dc/hubp/dcn50/,$(HUBP_DCN50))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_HUBP_DCN50)
+
+###############################################################################
+
 HUBP_DCN42 = dcn42_hubp.o
 
 AMD_DAL_HUBP_DCN42 = $(addprefix $(AMDDALPATH)/dc/hubp/dcn42/,$(HUBP_DCN42))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_HUBP_DCN42)
 
+###############################################################################
+
+HUBP_DCN60 = dcn60_hubp.o
+
+AMD_DAL_HUBP_DCN60 = $(addprefix $(AMDDALPATH)/dc/hubp/dcn60/,$(HUBP_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_HUBP_DCN60)
+
 endif
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/Makefile b/drivers/gpu/drm/amd/display/dc/hwss/Makefile
index df3101ce1784..9769ec9a32df 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/hwss/Makefile
@@ -201,6 +201,14 @@ AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN401)
 
 ###############################################################################
 
+HWSS_DCN50 = dcn50_hwseq.o
+
+AMD_DAL_HWSS_DCN50 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn50/,$(HWSS_DCN50))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN50)
+
+###############################################################################
+
 HWSS_DCN42 = dcn42_hwseq.o dcn42_init.o
 
 AMD_DAL_HWSS_DCN42 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn42/,$(HWSS_DCN42))
@@ -215,4 +223,12 @@ AMD_DAL_HWSS_DCN42B = $(addprefix $(AMDDALPATH)/dc/hwss/dcn42b/,$(HWSS_DCN42B))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN42B)
 
+###############################################################################
+
+HWSS_DCN60 = dcn60_hwseq.o dcn60_init.o
+
+AMD_DAL_HWSS_DCN60 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn60/,$(HWSS_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN60)
+
 endif
diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile
index 807b73c2a758..bbec53719c5d 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile
@@ -207,3 +207,12 @@ IRQ_DCN42 = irq_service_dcn42.o
 AMD_DAL_IRQ_DCN42= $(addprefix $(AMDDALPATH)/dc/irq/dcn42/,$(IRQ_DCN42))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCN42)
+
+###############################################################################
+# DCN 60
+###############################################################################
+IRQ_DCN60 = irq_service_dcn60.o
+
+AMD_DAL_IRQ_DCN60 = $(addprefix $(AMDDALPATH)/dc/irq/dcn60/,$(IRQ_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCN60)
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/Makefile b/drivers/gpu/drm/amd/display/dc/mpc/Makefile
index cc23aae3728a..65926e7c6611 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/mpc/Makefile
@@ -77,4 +77,12 @@ MPC_DCN42 = dcn42_mpc.o
 AMD_DAL_MPC_DCN42 = $(addprefix $(AMDDALPATH)/dc/mpc/dcn42/,$(MPC_DCN42))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_MPC_DCN42)
+###############################################################################
+# DCN60
+###############################################################################
+MPC_DCN60 = dcn60_mpc.o
+
+AMD_DAL_MPC_DCN60 = $(addprefix $(AMDDALPATH)/dc/mpc/dcn60/,$(MPC_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_MPC_DCN60)
 endif
diff --git a/drivers/gpu/drm/amd/display/dc/opp/Makefile b/drivers/gpu/drm/amd/display/dc/opp/Makefile
index 1be76754db30..7ac7cae268c8 100644
--- a/drivers/gpu/drm/amd/display/dc/opp/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/opp/Makefile
@@ -48,4 +48,12 @@ OPP_DCN35 = dcn35_opp.o
 AMD_DAL_OPP_DCN35 = $(addprefix $(AMDDALPATH)/dc/opp/dcn35/,$(OPP_DCN35))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_OPP_DCN35)
+###############################################################################
+# DCN60
+###############################################################################
+OPP_DCN60 = dcn60_opp.o
+
+AMD_DAL_OPP_DCN60 = $(addprefix $(AMDDALPATH)/dc/opp/dcn60/,$(OPP_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_OPP_DCN60)
 endif
diff --git a/drivers/gpu/drm/amd/display/dc/optc/Makefile b/drivers/gpu/drm/amd/display/dc/optc/Makefile
index 06c98d70eabc..4861ae265cf1 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/optc/Makefile
@@ -118,5 +118,14 @@ AMD_DAL_OPTC_DCN42 = $(addprefix $(AMDDALPATH)/dc/optc/dcn42/,$(OPTC_DCN42))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN42)
 
+###############################################################################
+
+OPTC_DCN60 = dcn60_optc.o
+
+AMD_DAL_OPTC_DCN60 = $(addprefix $(AMDDALPATH)/dc/optc/dcn60/,$(OPTC_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN60)
+
+###############################################################################
 endif
 
diff --git a/drivers/gpu/drm/amd/display/dc/resource/Makefile b/drivers/gpu/drm/amd/display/dc/resource/Makefile
index fe02ed39a3e9..b29986266888 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/resource/Makefile
@@ -246,5 +246,15 @@ RESOURCE_DCN42B = dcn42b_resource.o
 AMD_DAL_RESOURCE_DCN42B = $(addprefix $(AMDDALPATH)/dc/resource/dcn42b/,$(RESOURCE_DCN42B))
 
 AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN42B)
+
+
+###############################################################################
+
+RESOURCE_DCN60 = dcn60_resource.o
+
+AMD_DAL_RESOURCE_DCN60 = $(addprefix $(AMDDALPATH)/dc/resource/dcn60/,$(RESOURCE_DCN60))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN60)
+###############################################################################
 endif
 
diff --git a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/Makefile b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/Makefile
index 8a9bb0aef9b7..41de93f2659f 100644
--- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/Makefile
@@ -10,15 +10,18 @@ soc_and_ip_translator_rcflags := $(CC_FLAGS_NO_FPU)
 CFLAGS_$(AMDDALPATH)/dc/soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.o := $(soc_and_ip_translator_ccflags)
 CFLAGS_$(AMDDALPATH)/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.o := $(soc_and_ip_translator_ccflags)
 CFLAGS_$(AMDDALPATH)/dc/soc_and_ip_translator/dcn42b/dcn42b_soc_and_ip_translator.o := $(soc_and_ip_translator_ccflags)
+CFLAGS_$(AMDDALPATH)/dc/soc_and_ip_translator/dcn60/dcn60_soc_and_ip_translator.o := $(soc_and_ip_translator_ccflags)
 
 CFLAGS_REMOVE_$(AMDDALPATH)/dc/soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.o := $(soc_and_ip_translator_rcflags)
 CFLAGS_REMOVE_$(AMDDALPATH)/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.o := $(soc_and_ip_translator_rcflags)
 CFLAGS_REMOVE_$(AMDDALPATH)/dc/soc_and_ip_translator/dcn42b/dcn42b_soc_and_ip_translator.o := $(soc_and_ip_translator_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/soc_and_ip_translator/dcn60/dcn60_soc_and_ip_translator.o := $(soc_and_ip_translator_rcflags)
 
 soc_and_ip_translator := soc_and_ip_translator.o
 soc_and_ip_translator += dcn401/dcn401_soc_and_ip_translator.o
 soc_and_ip_translator += dcn42/dcn42_soc_and_ip_translator.o
 soc_and_ip_translator += dcn42b/dcn42b_soc_and_ip_translator.o
+soc_and_ip_translator += dcn60/dcn60_soc_and_ip_translator.o
 
 AMD_DAL_soc_and_ip_translator := $(addprefix $(AMDDALPATH)/dc/soc_and_ip_translator/, $(soc_and_ip_translator))
 
diff --git a/drivers/gpu/drm/amd/display/dmub/src/Makefile b/drivers/gpu/drm/amd/display/dmub/src/Makefile
index b6f7477ada22..2c5ec1fc0c5f 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/Makefile
+++ b/drivers/gpu/drm/amd/display/dmub/src/Makefile
@@ -30,6 +30,7 @@ DMUB += dmub_dcn36.o
 DMUB += dmub_dcn401.o
 DMUB += dmub_dcn42.o
 DMUB += dmub_dcn42b.o
+DMUB += dmub_dcn60.o
 
 AMD_DAL_DMUB = $(addprefix $(AMDDALPATH)/dmub/src/,$(DMUB))
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 06/41] drm/amd/display: Remove duplicate in tests/Makefile
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (2 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 05/41] drm/amd/display: Enable DCN6 sources compilation Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 07/41] drm/amd/display: Resize MST HDCP per-connector arrays to 32 Roman.Li
                   ` (35 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Wayne Lin

From: Roman Li <roman.li@amd.com>

The duplicate amdgpu_dm_plane_test.o entry causes linker errors
during the arm-64 build.

Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
index 3a51fccc2a5e..616881fcb9af 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/Makefile
@@ -35,4 +35,3 @@ obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_crtc_test.o
 obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_services_test.o
 obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_helpers_test.o
 obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_quirks_test.o
-obj-$(CONFIG_DRM_AMD_DC_KUNIT_TEST) += amdgpu_dm_plane_test.o
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 07/41] drm/amd/display: Resize MST HDCP per-connector arrays to 32
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (3 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 06/41] drm/amd/display: Remove duplicate in tests/Makefile Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 08/41] drm/amd/display: Bounds-check connector->index in dm_dp_mst_get_modes Roman.Li
                   ` (34 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen

From: Harry Wentland <harry.wentland@amd.com>

AMDGPU_DM_MAX_DISPLAY_INDEX is 31. It suggest a maximum number of
32 connectors. But the way it's used is like MAX_DISPLAY_COUNT.
Hence we're off by one with DRM core, which supports a max of 32
connectors.

Rename AMDGPU_DM_MAX_DISPLAY_INDEX to AMDGPU_DM_MAX_DISPLAY_COUNT
to match its actual use, and increase the size to 32 to match the
originally intended size.

Fixes: 82986fd631fa ("drm/amd/display: save restore hdcp state when display is unplugged from mst hub")
Assisted-by: Copilot:claude-opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c | 10 +++++-----
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h | 10 +++++-----
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
index c887a70ae74d..47cbc826ed45 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
@@ -365,7 +365,7 @@ void hdcp_reset_display(struct hdcp_workqueue *hdcp_work, unsigned int link_inde
 
 	cancel_delayed_work(&hdcp_w->property_validate_dwork);
 
-	for (conn_index = 0; conn_index < AMDGPU_DM_MAX_DISPLAY_INDEX; conn_index++) {
+	for (conn_index = 0; conn_index < AMDGPU_DM_MAX_DISPLAY_COUNT; conn_index++) {
 		hdcp_w->encryption_status[conn_index] =
 			MOD_HDCP_ENCRYPTION_STATUS_HDCP_OFF;
 		if (hdcp_w->aconnector[conn_index]) {
@@ -418,7 +418,7 @@ void event_property_update(struct work_struct *work)
 	struct drm_connector *connector;
 	struct drm_connector_state *conn_state;
 
-	for (conn_index = 0; conn_index < AMDGPU_DM_MAX_DISPLAY_INDEX; conn_index++) {
+	for (conn_index = 0; conn_index < AMDGPU_DM_MAX_DISPLAY_COUNT; conn_index++) {
 		aconnector = hdcp_work->aconnector[conn_index];
 
 		if (!aconnector)
@@ -478,7 +478,7 @@ void event_property_validate(struct work_struct *work)
 
 	guard(mutex)(&hdcp_work->mutex);
 
-	for (conn_index = 0; conn_index < AMDGPU_DM_MAX_DISPLAY_INDEX;
+	for (conn_index = 0; conn_index < AMDGPU_DM_MAX_DISPLAY_COUNT;
 	     conn_index++) {
 		aconnector = hdcp_work->aconnector[conn_index];
 
@@ -897,10 +897,10 @@ struct hdcp_workqueue *hdcp_create_workqueue(struct amdgpu_device *adev,
 
 		memset(hdcp_work[i].aconnector, 0,
 		       sizeof(struct amdgpu_dm_connector *) *
-			       AMDGPU_DM_MAX_DISPLAY_INDEX);
+			       AMDGPU_DM_MAX_DISPLAY_COUNT);
 		memset(hdcp_work[i].encryption_status, 0,
 		       sizeof(enum mod_hdcp_encryption_status) *
-			       AMDGPU_DM_MAX_DISPLAY_INDEX);
+			       AMDGPU_DM_MAX_DISPLAY_COUNT);
 	}
 
 	cp_psp->funcs.update_stream_config = update_config;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h
index 665fa4839a25..01c61e4d1176 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.h
@@ -36,7 +36,7 @@
  * Minimal declarations needed by this header.
  * Full amdgpu/DM definitions come from amdgpu_dm.h included by each .c file.
  */
-#define AMDGPU_DM_MAX_DISPLAY_INDEX 31
+#define AMDGPU_DM_MAX_DISPLAY_COUNT 32
 struct amdgpu_dm_connector;
 
 struct mod_hdcp;
@@ -57,7 +57,7 @@ struct hdcp_workqueue {
 	struct delayed_work callback_dwork;
 	struct delayed_work watchdog_timer_dwork;
 	struct delayed_work property_validate_dwork;
-	struct amdgpu_dm_connector *aconnector[AMDGPU_DM_MAX_DISPLAY_INDEX];
+	struct amdgpu_dm_connector *aconnector[AMDGPU_DM_MAX_DISPLAY_COUNT];
 	struct mutex mutex;
 
 	struct mod_hdcp hdcp;
@@ -65,7 +65,7 @@ struct hdcp_workqueue {
 	struct mod_hdcp_display display;
 	struct mod_hdcp_link link;
 
-	enum mod_hdcp_encryption_status encryption_status[AMDGPU_DM_MAX_DISPLAY_INDEX];
+	enum mod_hdcp_encryption_status encryption_status[AMDGPU_DM_MAX_DISPLAY_COUNT];
 	/* when display is unplugged from mst hub, connctor will be
 	 * destroyed within dm_dp_mst_connector_destroy. connector
 	 * hdcp perperties, like type, undesired, desired, enabled,
@@ -75,9 +75,9 @@ struct hdcp_workqueue {
 	 * will be retrieved from hdcp_work within dm_dp_mst_get_modes
 	 */
 	/* un-desired, desired, enabled */
-	unsigned int content_protection[AMDGPU_DM_MAX_DISPLAY_INDEX];
+	unsigned int content_protection[AMDGPU_DM_MAX_DISPLAY_COUNT];
 	/* hdcp1.x, hdcp2.x */
-	unsigned int hdcp_content_type[AMDGPU_DM_MAX_DISPLAY_INDEX];
+	unsigned int hdcp_content_type[AMDGPU_DM_MAX_DISPLAY_COUNT];
 
 	uint8_t max_link;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 08/41] drm/amd/display: Bounds-check connector->index in dm_dp_mst_get_modes
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (4 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 07/41] drm/amd/display: Resize MST HDCP per-connector arrays to 32 Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 09/41] drm/amd/display: Ensure dtbclk is enabled Roman.Li
                   ` (33 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen

From: Harry Wentland <harry.wentland@amd.com>

dm_dp_mst_get_modes() uses drm_connector->index to index the
per-connector HDCP arrays in struct hdcp_workqueue. Those arrays are
sized to AMDGPU_DM_MAX_DISPLAY_COUNT, which matches the DRM connector
index range (0..31). Add a defensive bounds check so that, should the
DRM connector index range ever grow beyond the array size, the access
is skipped instead of reading and writing out of bounds.

Assisted-by: Copilot:claude-opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
index e001d868db80..045a7f88b754 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
@@ -485,7 +485,8 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector)
 			struct drm_device *dev = connector->dev;
 			struct amdgpu_device *adev = drm_to_adev(dev);
 
-			if (adev->dm.hdcp_workqueue) {
+			if (adev->dm.hdcp_workqueue &&
+			    connector->index < AMDGPU_DM_MAX_DISPLAY_COUNT) {
 				struct hdcp_workqueue *hdcp_work = adev->dm.hdcp_workqueue;
 				struct hdcp_workqueue *hdcp_w =
 					&hdcp_work[aconnector->dc_link->link_index];
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 09/41] drm/amd/display: Ensure dtbclk is enabled
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (5 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 08/41] drm/amd/display: Bounds-check connector->index in dm_dp_mst_get_modes Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 10/41] drm/amd/display: Update VRR info packet to support 12-bit refresh rates Roman.Li
                   ` (32 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Charlene Liu, Chris Park,
	Leo Chen

From: Charlene Liu <Charlene.Liu@amd.com>

[why]
ensure dtbclk is enabled before hdmistreamclk_en

pmfw could stop dtbclk on idle.
driver needs to ensure dtbclk enabled is enabled before hdmistreamclk_en
also disable debounce timer on dcn42.

Reviewed-by: Chris Park <chris.park@amd.com>
Reviewed-by: Leo Chen <leo.chen@amd.com>
Signed-off-by: Charlene Liu <Charlene.Liu@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c  | 28 +++++++++++++++++--
 .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h  |  1 +
 .../drm/amd/display/dc/dce/dce_clock_source.c |  4 +++
 .../gpu/drm/amd/display/dc/inc/hw/clk_mgr.h   |  1 +
 .../display/dc/link/protocols/link_hdmi_frl.c | 18 ++++++++++--
 5 files changed, 46 insertions(+), 6 deletions(-)

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
index c7b9bad93a93..19ef0b92e8e6 100644
--- 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
@@ -220,6 +220,7 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
 	bool update_dispclk = false;
 	bool dpp_clock_lowered = false;
 	bool has_active_display;
+	int actual_dtbclk = 0;
 
 	if (dc->work_arounds.skip_clock_update)
 		return;
@@ -260,8 +261,9 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
 		 * For dcn42b (no dtbclk hardware), init_clk_states sets dtbclk_en=false and
 		 * new_clocks->dtbclk_en should always be false, so this block never executes.
 		 */
-		if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) {
-			int actual_dtbclk = 0;
+		actual_dtbclk = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dtbclk);
+
+		if (new_clocks->dtbclk_en && actual_dtbclk < 590000) {
 
 			dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
 			dcn42_smu_set_dtbclk(clk_mgr, true);
@@ -343,7 +345,6 @@ void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
 		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);
@@ -1051,7 +1052,27 @@ void dcn42_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int)
 		dm_helpers_free_gpu_mem(clk_mgr_base->ctx, DC_MEM_ALLOC_TYPE_GART,
 				smu_dpm_clks.dpm_clks);
 }
+void dcn42_request_dtbclk(struct clk_mgr *clk_mgr_base, bool enable)
+{
+	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+	/*pmfw might turn off dtblck based on allow_dtbstop*/
+	clk_mgr_base->clks.dtbclk_en = false;
 
+	if (enable) {
+		int actual_dtbclk = 0;
+
+		dcn42_smu_set_dtbclk(clk_mgr, true);
+		actual_dtbclk = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dtbclk);
+		if (actual_dtbclk > 590000) {
+			clk_mgr_base->clks.ref_dtbclk_khz = actual_dtbclk;
+			clk_mgr_base->clks.dtbclk_en = true;
+		}
+	} else {
+		clk_mgr_base->clks.dtbclk_en = false;
+		dcn42_smu_set_dtbclk(clk_mgr, false);
+	}
+}
 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,
@@ -1065,6 +1086,7 @@ static struct clk_mgr_funcs dcn42_funcs = {
 	.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,
+	.request_dtbclk = dcn42_request_dtbclk,
 	.notify_cstate_disable = dcn42_notify_cstate_disable,
 };
 
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
index 330242747fff..f90c6e2e85c2 100644
--- 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
@@ -84,4 +84,5 @@ void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, struct dcn42
 void dcn42_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int);
 void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr, struct dc_state *context, bool safe_to_lower);
 int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base);
+void dcn42_request_dtbclk(struct clk_mgr *clk_mgr_base, bool enable);
 #endif //__DCN42_CLK_MGR_H__
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index e52fb7248a88..47ec08071ceb 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -1118,6 +1118,10 @@ static bool dcn401_program_pix_clk(
 		if (clock_source->ctx->dc->caps.is_apu &&
 			pix_clk_params->requested_pix_clk_100hz &&
 			dc_is_hdmi_frl_signal(pix_clk_params->signal_type)) {
+			//make sure dtbclk is enabled
+			if (clock_source->ctx->dc->clk_mgr->funcs->request_dtbclk)
+				clock_source->ctx->dc->clk_mgr->funcs->request_dtbclk(
+					clock_source->ctx->dc->clk_mgr, true);
 			/*need hdmistreamclk before vpg block register access*/
 			clock_source->ctx->dc->res_pool->dccg->funcs->set_hdmistreamclk(
 				clock_source->ctx->dc->res_pool->dccg,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
index ec678bd249ef..614beb5924fd 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
@@ -427,6 +427,7 @@ struct clk_mgr_funcs {
 			struct block_sequence_state *seq_state);
 
 	void (*execute_clk_mgr_block_sequence)(struct clk_mgr *clk_mgr);
+	void (*request_dtbclk)(struct clk_mgr *clk_mgr_base, bool enable);
 };
 
 struct clk_mgr {
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
index 75ec3b701d81..714168e1ece6 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_hdmi_frl.c
@@ -415,6 +415,18 @@ void hdmi_frl_LTS_clear_Link_Setting(struct ddc_service *ddc_service)
 
 }
 
+static uint8_t hdmi_frl_get_max_ffe_level(struct dc_link *link,
+		struct dc_hdmi_frl_link_settings *link_settings)
+{
+	uint8_t max_ffe_level =
+			(link_settings->frl_link_rate > HDMI_FRL_LINK_RATE_12GBPS) ? 7 : 3;
+
+	if ((uint8_t)link->dc->debug.limit_ffe < max_ffe_level)
+		max_ffe_level = (uint8_t)link->dc->debug.limit_ffe;
+
+	return max_ffe_level;
+}
+
 static enum link_result hdmi_frl_perform_link_training(struct ddc_service *ddc_service,
 		struct dc_hdmi_frl_link_settings *link_settings)
 {
@@ -436,7 +448,7 @@ static enum link_result hdmi_frl_perform_link_training(struct ddc_service *ddc_s
 	struct hpo_frl_link_encoder *hpo_frl_link_enc = ddc_service->link->hpo_frl_link_enc;
 	struct link_encoder *dio_link_enc = ddc_service->link->link_enc;
 	uint8_t sink_version = 0;
-	uint8_t FFE_Levels = (uint8_t)ddc_service->link->dc->debug.limit_ffe;
+	uint8_t FFE_Levels = hdmi_frl_get_max_ffe_level(ddc_service->link, link_settings);
 	uint8_t current_FFE = 0;
 	bool override_FFE = false;
 	bool flt_no_timeout = false;
@@ -616,7 +628,7 @@ static enum link_result hdmi_frl_perform_link_training(struct ddc_service *ddc_s
 						}
 						current_FFE++;
 						override_FFE = true;
-						if (current_FFE > 3)
+						if (current_FFE > FFE_Levels)
 							current_FFE = 0;
 						if (flt_no_timeout)
 							current_FFE = 0;
@@ -642,7 +654,7 @@ static enum link_result hdmi_frl_perform_link_training(struct ddc_service *ddc_s
 						}
 						current_FFE++;
 						override_FFE = true;
-						if (current_FFE > 3)
+						if (current_FFE > FFE_Levels)
 							current_FFE = 0;
 						if (flt_no_timeout)
 							current_FFE = 0;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 10/41] drm/amd/display: Update VRR info packet to support 12-bit refresh rates
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (6 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 09/41] drm/amd/display: Ensure dtbclk is enabled Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 11/41] drm/amd/display: Gate HDMI FRL status polling on active FRL link rate Roman.Li
                   ` (31 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Harry VanZyllDeJong,
	Anthony Koo

From: Harry VanZyllDeJong <hvanzyll@amd.com>

[Why]
VRR info packet previously only supported up to 10-bit refresh rate values
limiting the range of FreeSync minimum and maximum refresh rates that
could be encoded.

[How]
Expanded the bit masking in PB11/PB12 from 2 to 4 bits to capture bits
11:8 of the minimum and maximum FreeSync refresh rates, enabling the VRR
info packet to encode 12-bit refresh rate values.

Reviewed-by: Anthony Koo <anthony.koo@amd.com>
Signed-off-by: Harry VanZyllDeJong <hvanzyll@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index f3b41087678b..4bd060e30799 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -684,11 +684,11 @@ static void build_vrr_infopacket_data_v3(const struct mod_vrr_params *vrr,
 	/* PB8 = FreeSync Maximum refresh rate (Hz) */
 	infopacket->sb[8] = max_refresh & 0xFF;
 
-	/* PB11 : MSB FreeSync Minimum refresh rate [Hz] - bits 9:8 */
-	infopacket->sb[11] = (min_programmed >> 8) & 0x03;
+	/* PB11 : MSB FreeSync Minimum refresh rate [Hz] - bits 11:8 */
+	infopacket->sb[11] = (min_programmed >> 8) & 0x0F;
 
-	/* PB12 : MSB FreeSync Maximum refresh rate [Hz] - bits 9:8 */
-	infopacket->sb[12] = (max_refresh >> 8) & 0x03;
+	/* PB12 : MSB FreeSync Maximum refresh rate [Hz] - bits 11:8 */
+	infopacket->sb[12] = (max_refresh >> 8) & 0x0F;
 
 	/* PB16 : Reserved bits 7:1, FixedRate bit 0 */
 	infopacket->sb[16] = (vrr->state == VRR_STATE_ACTIVE_FIXED) ? 1 : 0;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 11/41] drm/amd/display: Gate HDMI FRL status polling on active FRL link rate
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (7 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 10/41] drm/amd/display: Update VRR info packet to support 12-bit refresh rates Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 12/41] drm/amd/display: Fix wb_info leak and NULL deref in writeback Roman.Li
                   ` (30 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen

From: Fangzhi Zuo <jerry.zuo@amd.com>

[Why]
hdmi_frl_status_polling_work() skipped any link whose connector_signal
was not SIGNAL_TYPE_HDMI_FRL. connector_signal is not reliably set to
SIGNAL_TYPE_HDMI_FRL while a link is actually running FRL, so links that
were operating in FRL mode were skipped and their status flags never got
polled, missing link-retrain events.

[How]
Use frl_link_settings.frl_link_rate to decide whether a link is running
FRL. A non-zero rate means FRL is active, so only links with a zero rate
are skipped. This ensures every link actually operating in FRL mode is
polled for status changes.

Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
index a8f089d4fb72..e637db2723c1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
@@ -3009,7 +3009,7 @@ static void hdmi_frl_status_polling_work(struct work_struct *work)
 		if (!dc_is_hdmi_signal(dc_link->connector_signal))
 			continue;
 
-		if (dc_link->connector_signal != SIGNAL_TYPE_HDMI_FRL)
+		if (dc_link->frl_link_settings.frl_link_rate == 0)
 			continue;
 
 		link_update = dc_link_frl_poll_status_flag(dc_link);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 12/41] drm/amd/display: Fix wb_info leak and NULL deref in writeback
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (8 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 11/41] drm/amd/display: Gate HDMI FRL status polling on active FRL link rate Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 13/41] drm/amd/display: Fix seamless mode switch not triggering for HDR to SDR transition Roman.Li
                   ` (29 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen

From: Alex Hung <alex.hung@amd.com>

[WHAT]
dc_stream_add_writeback() copies wb_info by value, so free it on all
paths via a single cleanup label. Also bail out early when no pipe_ctx
matches the stream to avoid a NULL pointer dereference.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c    | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 0dcf829c1d07..52c1ffad985b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4647,21 +4647,19 @@ static void dm_set_writeback(struct amdgpu_display_manager *dm,
 	wb_info = kzalloc_obj(*wb_info);
 	if (!wb_info) {
 		drm_err(adev_to_drm(adev), "Failed to allocate wb_info\n");
-		return;
+		goto cleanup;
 	}
 
 	acrtc = to_amdgpu_crtc(wb_conn->encoder.crtc);
 	if (!acrtc) {
 		drm_err(adev_to_drm(adev), "no amdgpu_crtc found\n");
-		kfree(wb_info);
-		return;
+		goto cleanup;
 	}
 
 	afb = to_amdgpu_framebuffer(new_con_state->writeback_job->fb);
 	if (!afb) {
 		drm_err(adev_to_drm(adev), "No amdgpu_framebuffer found\n");
-		kfree(wb_info);
-		return;
+		goto cleanup;
 	}
 
 	for (i = 0; i < MAX_PIPES; i++) {
@@ -4671,6 +4669,11 @@ static void dm_set_writeback(struct amdgpu_display_manager *dm,
 		}
 	}
 
+	if (!pipe) {
+		drm_err(adev_to_drm(adev), "No pipe found for stream\n");
+		goto cleanup;
+	}
+
 	/* fill in wb_info */
 	wb_info->wb_enabled = true;
 
@@ -4744,6 +4747,9 @@ static void dm_set_writeback(struct amdgpu_display_manager *dm,
 	WARN_ON(drm_crtc_vblank_get(&acrtc->base));
 	acrtc->wb_frame_done = false;
 	acrtc->wb_pending = true;
+
+cleanup:
+	kfree(wb_info);
 }
 
 static void amdgpu_dm_update_hdcp(struct drm_atomic_commit *state)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 13/41] drm/amd/display: Fix seamless mode switch not triggering for HDR to SDR transition
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (9 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 12/41] drm/amd/display: Fix wb_info leak and NULL deref in writeback Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 14/41] drm/amd/display: Add KUnit tests for more crtc functions Roman.Li
                   ` (28 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Karthi Kandasamy, Aric Cyr

From: Karthi Kandasamy <karthi.kandasamy@amd.com>

[Why]
The seamless mode switch was not getting triggered during HDR to SDR
transitions, and no DPCD write was observed. Root cause analysis
revealed that incorrect panel capabilities were being reported for PSR
SU panels. Due to the wrong capabilities, the OS was not invoking the
seamless mode switch API, resulting in no DPCD communication and also
gated eDP teardown across the seamless mode switch hold.

[How]
Fixed by setting the correct power panel capabilities for PSR SU panels.
This ensures the OS receives accurate panel capability information and
triggers the seamless mode switch API as expected, restoring proper
DPCD writes during HDR to SDR transitions.
The DC commit sequence was tearing the eDP down anyway -- backlight off,
ABM disable, DPMS off, PSR/Replay enable state cleared, PHY TX off,
OTG/OPTC off; all these actions are blocked now with the
skip_implict_edp_power_control

Reviewed-by: Aric Cyr <aric.cyr@amd.com>
Signed-off-by: Karthi Kandasamy <karthi.kandasamy@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 drivers/gpu/drm/amd/display/dc/dc.h           |  1 +
 .../amd/display/dc/hwss/dce110/dce110_hwseq.c | 10 ++++++--
 .../amd/display/dc/hwss/dcn31/dcn31_hwseq.c   | 21 ++++++++++++-----
 .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c   |  7 ++++--
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 23 ++++++++++++++-----
 .../drm/amd/display/modules/power/power_psr.c |  7 ++++++
 .../amd/display/modules/power/power_replay.c  |  7 ++++++
 7 files changed, 60 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index cc029af0cef2..683b5fb1945d 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1994,6 +1994,7 @@ struct dc_scratch_space {
 	// BW ALLOCATON USB4 ONLY
 	struct dc_dpia_bw_alloc dpia_bw_alloc_config;
 	bool skip_implict_edp_power_control;
+	bool forced_psr_active;
 	enum backlight_control_type backlight_control_type;
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
index 5fcf30b448a5..80180cb00aba 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
@@ -1286,6 +1286,8 @@ void dce110_blank_stream(struct pipe_ctx *pipe_ctx)
 		return;
 
 	if (link->local_sink && link->local_sink->sink_signal == SIGNAL_TYPE_EDP) {
+		if (link->forced_psr_active)
+			return;
 		if (!link->skip_implict_edp_power_control && hws)
 			hws->funcs.edp_backlight_control(link, false);
 		link->dc->hwss.set_abm_immediate_disable(pipe_ctx);
@@ -1811,7 +1813,9 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw(
 			dc->link_srv->set_dsc_enable(pipe_ctx, true);
 	}
 
-	if (!stream->dpms_off)
+	if (!stream->dpms_off &&
+	    !(link->connector_signal == SIGNAL_TYPE_EDP &&
+	      link->forced_psr_active))
 		dc->link_srv->set_dpms_on(context, pipe_ctx);
 
 	/* DCN3.1 FPGA Workaround
@@ -1830,7 +1834,9 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw(
 	 * is constructed with the same sink). Make sure not to override
 	 * and link programming on the main.
 	 */
-	if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM) {
+	if (dc_state_get_pipe_subvp_type(context, pipe_ctx) != SUBVP_PHANTOM &&
+	    !(link->connector_signal == SIGNAL_TYPE_EDP &&
+	      link->forced_psr_active)) {
 		pipe_ctx->stream->link->psr_settings.psr_feature_enabled = false;
 		pipe_ctx->stream->link->replay_settings.replay_feature_enabled = false;
 	}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
index b6f3c0480ab6..823ef06c64f5 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c
@@ -537,10 +537,12 @@ static void dcn31_reset_back_end_for_pipe(
 	}
 	ASSERT(!pipe_ctx->top_pipe);
 
-	dc->hwss.set_abm_immediate_disable(pipe_ctx);
-
 	link = pipe_ctx->stream->link;
 
+	if (!(link->connector_signal == SIGNAL_TYPE_EDP &&
+	      link->forced_psr_active))
+		dc->hwss.set_abm_immediate_disable(pipe_ctx);
+
 	if (dc->hwseq)
 		dc->hwseq->wa_state.skip_blank_stream = false;
 
@@ -555,9 +557,11 @@ static void dcn31_reset_back_end_for_pipe(
 			pipe_ctx->stream_res.tg,
 			OPTC_DSC_DISABLED, 0, 0);
 
-	pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
-
-	pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
+	if (!(link->connector_signal == SIGNAL_TYPE_EDP &&
+	      link->forced_psr_active)) {
+		pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
+		pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
+	}
 	if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
 		pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
 				pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
@@ -586,7 +590,12 @@ static void dcn31_reset_back_end_for_pipe(
 	 * screen only, the dpms_off would be true but
 	 * VBIOS lit up eDP, so check link status too.
 	 */
-	if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
+	if (link->connector_signal == SIGNAL_TYPE_EDP &&
+	    link->forced_psr_active) {
+		/* forced psr is active for seamless switch; skip dpms-off. */
+		if (pipe_ctx->stream_res.audio)
+			dc->hwss.disable_audio_stream(pipe_ctx);
+	} else if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
 		dc->link_srv->set_dpms_off(pipe_ctx);
 	else if (pipe_ctx->stream_res.audio)
 		dc->hwss.disable_audio_stream(pipe_ctx);
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
index 08f1f307657c..6e1079377f48 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
@@ -1819,8 +1819,11 @@ void dcn35_disable_link_output(struct dc_link *link,
 		disable_link_output_symclk_on_tx_off(link, DP_UNKNOWN_ENCODING);
 		link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
 	} else {
-		link_hwss->disable_link_output(link, link_res, signal);
-		link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
+		if (!(signal == SIGNAL_TYPE_EDP &&
+		      link->forced_psr_active)) {
+			link_hwss->disable_link_output(link, link_res, signal);
+			link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
+		}
 	}
 	/*
 	 * Add the logic to extract BOTH power up and power down sequences
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index b89010a88b44..904780e02f70 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -1113,8 +1113,11 @@ void dcn401_disable_link_output(struct dc_link *link,
 		disable_link_output_symclk_on_tx_off(link, DP_UNKNOWN_ENCODING);
 		link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
 	} else {
-		link_hwss->disable_link_output(link, link_res, signal);
-		link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
+		if (!(signal == SIGNAL_TYPE_EDP &&
+		      link->forced_psr_active)) {
+			link_hwss->disable_link_output(link, link_res, signal);
+			link->phy_state.symclk_state = SYMCLK_OFF_TX_OFF;
+		}
 	}
 
 	if (signal == SIGNAL_TYPE_EDP &&
@@ -2162,7 +2165,12 @@ void dcn401_reset_back_end_for_pipe(
 	 * screen only, the dpms_off would be true but
 	 * VBIOS lit up eDP, so check link status too.
 	 */
-	if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
+	if (link->connector_signal == SIGNAL_TYPE_EDP &&
+	    link->forced_psr_active) {
+		/* Forced psr is active for seamless switch; skip dpms-off. */
+		if (pipe_ctx->stream_res.audio)
+			dc->hwss.disable_audio_stream(pipe_ctx);
+	} else if (!pipe_ctx->stream->dpms_off || link->link_status.link_active)
 		dc->link_srv->set_dpms_off(pipe_ctx);
 	else if (pipe_ctx->stream_res.audio)
 		dc->hwss.disable_audio_stream(pipe_ctx);
@@ -2187,12 +2195,15 @@ void dcn401_reset_back_end_for_pipe(
 	 * parent pipe.
 	 */
 	if (pipe_ctx->top_pipe == NULL) {
+		if (!(link->connector_signal == SIGNAL_TYPE_EDP &&
+		      link->forced_psr_active)) {
 
-		dc->hwss.set_abm_immediate_disable(pipe_ctx);
+			dc->hwss.set_abm_immediate_disable(pipe_ctx);
 
-		pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
+			pipe_ctx->stream_res.tg->funcs->disable_crtc(pipe_ctx->stream_res.tg);
 
-		pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
+			pipe_ctx->stream_res.tg->funcs->enable_optc_clock(pipe_ctx->stream_res.tg, false);
+		}
 		if (pipe_ctx->stream_res.tg->funcs->set_odm_bypass)
 			pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
 					pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_psr.c b/drivers/gpu/drm/amd/display/modules/power/power_psr.c
index 5ecb570c204e..96bb77fff05b 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_psr.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_psr.c
@@ -58,6 +58,13 @@ bool mod_power_psr_notify_mode_change(struct mod_power *mod_power,
 	// stream_index is passed as validated parameter
 	active_psr_events = core_power->map[stream_index].psr_events;
 
+	/* forced psr is active for seamless switch.
+	 * Re-running edp_setup_psr would disturb the freeze,
+	 * so skip the PSR re-setup until forced psr releases the override.
+	 */
+	if (active_psr_events & psr_event_os_override_hold)
+		return false;
+
 	/* Calculate PSR configurations */
 	mod_power_calc_psr_configs(&psr_config, link, stream);
 
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_replay.c b/drivers/gpu/drm/amd/display/modules/power/power_replay.c
index e782501442c4..31d9cb3a12ba 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_replay.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_replay.c
@@ -805,6 +805,13 @@ void mod_power_replay_notify_mode_change(struct mod_power *mod_power,
 	core_power = MOD_POWER_TO_CORE(mod_power);
 	active_replay_events = core_power->map[stream_index].replay_events;
 
+	/* forced psr is active for seamless switch.
+	 * Re-running edp_setup_psr would disturb the freeze,
+	 * so skip the PSR re-setup until forced psr releases the override.
+	 */
+	if (active_replay_events & replay_event_os_override_hold)
+		return;
+
 	link->replay_settings.replay_smu_opt_enable =
 		(link->replay_settings.config.replay_smu_opt_supported &&
 		mod_power_only_edp(dc->current_state, stream));
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 14/41] drm/amd/display: Add KUnit tests for more crtc functions
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (10 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 13/41] drm/amd/display: Fix seamless mode switch not triggering for HDR to SDR transition Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 15/41] drm/amd/display: Add vblank handling tests for crtc Roman.Li
                   ` (27 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha

From: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>

Expand KUnit coverage for amdgpu_dm_crtc.c with tests for functions that
are easy to exercise in isolation:

- amdgpu_dm_crtc_set_static_screen_optimze(): the !allow_sr_entry early
  return.
- amdgpu_dm_crtc_enable_vblank(): rejection with -EINVAL when enabling
  vblank on an unconfigured CRTC.
- amdgpu_dm_crtc_update_crtc_active_planes(): the no-stream branch that
  resets active_planes to zero.
- amdgpu_dm_crtc_duplicate_state(): DM-specific fields are carried over.
- amdgpu_dm_crtc_reset_state(): a fresh state is allocated and installed.
- amdgpu_dm_crtc_destroy_state(): a stream-less state is freed cleanly.

Expose amdgpu_dm_crtc_destroy_state(), amdgpu_dm_crtc_duplicate_state(),
amdgpu_dm_crtc_reset_state() and amdgpu_dm_crtc_update_crtc_active_planes()
to the tests via STATIC_IFN_KUNIT/EXPORT_IF_KUNIT.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |  14 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.h    |   6 +
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 177 ++++++++++++++++++
 3 files changed, 193 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index 079d4ccc88da..ce42102109bb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -134,6 +134,7 @@ void amdgpu_dm_crtc_set_static_screen_optimze(
 		amdgpu_dm_psr_set_event(dm, stream,
 			set_vsync_event, psr_event_vsync, set_vsync_event);
 }
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_set_static_screen_optimze);
 
 bool amdgpu_dm_is_headless(struct amdgpu_device *adev)
 {
@@ -393,13 +394,14 @@ int amdgpu_dm_crtc_enable_vblank(struct drm_crtc *crtc)
 {
 	return amdgpu_dm_crtc_set_vblank(crtc, true);
 }
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_enable_vblank);
 
 void amdgpu_dm_crtc_disable_vblank(struct drm_crtc *crtc)
 {
 	amdgpu_dm_crtc_set_vblank(crtc, false);
 }
 
-static void amdgpu_dm_crtc_destroy_state(struct drm_crtc *crtc,
+STATIC_IFN_KUNIT void amdgpu_dm_crtc_destroy_state(struct drm_crtc *crtc,
 				  struct drm_crtc_state *state)
 {
 	struct dm_crtc_state *cur = to_dm_crtc_state(state);
@@ -414,8 +416,9 @@ static void amdgpu_dm_crtc_destroy_state(struct drm_crtc *crtc,
 
 	kfree(state);
 }
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_destroy_state);
 
-static struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *crtc)
+STATIC_IFN_KUNIT struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *crtc)
 {
 	struct dm_crtc_state *state, *cur;
 
@@ -450,6 +453,7 @@ static struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *cr
 
 	return &state->base;
 }
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_duplicate_state);
 
 static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc)
 {
@@ -463,7 +467,7 @@ static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc)
 	kfree(crtc);
 }
 
-static void amdgpu_dm_crtc_reset_state(struct drm_crtc *crtc)
+STATIC_IFN_KUNIT void amdgpu_dm_crtc_reset_state(struct drm_crtc *crtc)
 {
 	struct dm_crtc_state *state;
 
@@ -476,6 +480,7 @@ static void amdgpu_dm_crtc_reset_state(struct drm_crtc *crtc)
 
 	__drm_atomic_helper_crtc_reset(crtc, &state->base);
 }
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_reset_state);
 
 #ifdef CONFIG_DEBUG_FS
 static int amdgpu_dm_crtc_late_register(struct drm_crtc *crtc)
@@ -610,7 +615,7 @@ static int amdgpu_dm_crtc_count_crtc_active_planes(struct drm_crtc_state *new_cr
 	return num_active;
 }
 
-static void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc,
+STATIC_IFN_KUNIT void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc,
 						     struct drm_crtc_state *new_crtc_state)
 {
 	struct dm_crtc_state *dm_new_crtc_state =
@@ -624,6 +629,7 @@ static void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc,
 	dm_new_crtc_state->active_planes =
 		amdgpu_dm_crtc_count_crtc_active_planes(new_crtc_state);
 }
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_update_crtc_active_planes);
 
 STATIC_IFN_KUNIT bool amdgpu_dm_crtc_helper_mode_fixup(struct drm_crtc *crtc,
 					       const struct drm_display_mode *mode,
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
index d8b004f613ab..ed6e8021d69e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
@@ -46,6 +46,12 @@ bool amdgpu_dm_crtc_vrr_active_irq(struct amdgpu_crtc *acrtc);
 bool amdgpu_dm_crtc_helper_mode_fixup(struct drm_crtc *crtc,
 				      const struct drm_display_mode *mode,
 				      struct drm_display_mode *adjusted_mode);
+void amdgpu_dm_crtc_destroy_state(struct drm_crtc *crtc,
+				  struct drm_crtc_state *state);
+struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *crtc);
+void amdgpu_dm_crtc_reset_state(struct drm_crtc *crtc);
+void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc,
+					      struct drm_crtc_state *new_crtc_state);
 #endif
 
 bool amdgpu_dm_crtc_vrr_active(const struct dm_crtc_state *dm_state);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index ac21bbec92ab..ce20692959d0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -456,6 +456,171 @@ static void dm_test_idle_create_workqueue(struct kunit *test)
 	kfree(idle_work);
 }
 
+/* Tests for amdgpu_dm_crtc_set_static_screen_optimze() */
+
+/**
+ * dm_test_crtc_set_static_screen_optimze_no_sr_entry - Test early return when SR entry disallowed
+ * @test: The KUnit test context
+ *
+ * When self-refresh entry is not allowed the function must return immediately
+ * without touching replay or PSR events, regardless of the requested SSO state.
+ */
+static void dm_test_crtc_set_static_screen_optimze_no_sr_entry(struct kunit *test)
+{
+	struct amdgpu_display_manager *dm;
+	struct dc_link *link;
+	struct dc_stream_state *stream;
+
+	dm = kunit_kzalloc(test, sizeof(*dm), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm);
+
+	link = dm_kunit_alloc_link(test);
+	stream = dm_kunit_alloc_stream(test, link);
+
+	/* allow_sr_entry == false -> returns before any event is set. */
+	amdgpu_dm_crtc_set_static_screen_optimze(dm, stream, true, false);
+	amdgpu_dm_crtc_set_static_screen_optimze(dm, stream, false, false);
+}
+
+/* Tests for amdgpu_dm_crtc_enable_vblank() */
+
+/**
+ * dm_test_crtc_enable_vblank_rejects_unconfigured - Test vblank enable on disabled CRTC
+ * @test: The KUnit test context
+ *
+ * Enabling vblank on a CRTC that is not enabled must be rejected with -EINVAL
+ * before any interrupt state is touched.
+ */
+static void dm_test_crtc_enable_vblank_rejects_unconfigured(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+	struct amdgpu_crtc *acrtc;
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
+
+	acrtc->base.dev = &adev->ddev;
+	acrtc->base.enabled = false;
+
+	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), -EINVAL);
+}
+
+/* Tests for amdgpu_dm_crtc_update_crtc_active_planes() */
+
+/**
+ * dm_test_crtc_update_active_planes_no_stream - Test active plane reset without a stream
+ * @test: The KUnit test context
+ *
+ * Without a DC stream attached the active plane count must be reset to zero
+ * and the plane-counting path must be skipped.
+ */
+static void dm_test_crtc_update_active_planes_no_stream(struct kunit *test)
+{
+	struct dm_crtc_state *dm_state;
+
+	dm_state = kunit_kzalloc(test, sizeof(*dm_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
+
+	dm_state->stream = NULL;
+	dm_state->active_planes = 5;
+
+	amdgpu_dm_crtc_update_crtc_active_planes(NULL, &dm_state->base);
+
+	KUNIT_EXPECT_EQ(test, dm_state->active_planes, 0);
+}
+
+/* Tests for amdgpu_dm_crtc_duplicate_state() */
+
+/**
+ * dm_test_crtc_duplicate_state_copies_fields - Test duplicated state carries DM fields
+ * @test: The KUnit test context
+ *
+ * Duplicating a CRTC state without a stream must produce a new state that
+ * carries over the DM-specific fields from the current state.
+ */
+static void dm_test_crtc_duplicate_state_copies_fields(struct kunit *test)
+{
+	struct drm_crtc *crtc;
+	struct dm_crtc_state *cur;
+	struct drm_crtc_state *dup;
+	struct dm_crtc_state *dm_dup;
+
+	crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
+	cur = kunit_kzalloc(test, sizeof(*cur), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, cur);
+
+	cur->abm_level = 3;
+	cur->active_planes = 2;
+	cur->vrr_supported = true;
+	cur->cm_has_degamma = true;
+	cur->cm_is_degamma_srgb = true;
+	cur->crc_skip_count = 7;
+	cur->mpo_requested = true;
+	crtc->state = &cur->base;
+
+	dup = amdgpu_dm_crtc_duplicate_state(crtc);
+	KUNIT_ASSERT_NOT_NULL(test, dup);
+
+	dm_dup = to_dm_crtc_state(dup);
+	KUNIT_EXPECT_EQ(test, dm_dup->abm_level, 3);
+	KUNIT_EXPECT_EQ(test, dm_dup->active_planes, 2);
+	KUNIT_EXPECT_TRUE(test, dm_dup->vrr_supported);
+	KUNIT_EXPECT_TRUE(test, dm_dup->cm_has_degamma);
+	KUNIT_EXPECT_TRUE(test, dm_dup->cm_is_degamma_srgb);
+	KUNIT_EXPECT_EQ(test, dm_dup->crc_skip_count, 7);
+	KUNIT_EXPECT_TRUE(test, dm_dup->mpo_requested);
+
+	amdgpu_dm_crtc_destroy_state(crtc, dup);
+}
+
+/* Tests for amdgpu_dm_crtc_reset_state() */
+
+/**
+ * dm_test_crtc_reset_state_allocates_state - Test reset installs a fresh state
+ * @test: The KUnit test context
+ *
+ * Resetting a CRTC with no existing state must allocate and install a new
+ * drm_crtc_state.
+ */
+static void dm_test_crtc_reset_state_allocates_state(struct kunit *test)
+{
+	struct amdgpu_device *adev = dm_kunit_alloc_adev(test);
+	struct drm_crtc *crtc;
+
+	crtc = kunit_kzalloc(test, sizeof(*crtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc);
+	crtc->dev = &adev->ddev;
+	crtc->state = NULL;
+
+	amdgpu_dm_crtc_reset_state(crtc);
+
+	KUNIT_EXPECT_NOT_NULL(test, crtc->state);
+
+	if (crtc->state)
+		amdgpu_dm_crtc_destroy_state(crtc, crtc->state);
+}
+
+/* Tests for amdgpu_dm_crtc_destroy_state() */
+
+/**
+ * dm_test_crtc_destroy_state_no_stream - Test destroy frees a stream-less state
+ * @test: The KUnit test context
+ *
+ * Destroying a CRTC state with no stream attached must free the state without
+ * attempting to release a DC stream.
+ */
+static void dm_test_crtc_destroy_state_no_stream(struct kunit *test)
+{
+	struct dm_crtc_state *dm_state;
+
+	/* destroy_state kfree()s the state, so use a plain (unmanaged) alloc. */
+	dm_state = kzalloc_obj(*dm_state, GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
+
+	amdgpu_dm_crtc_destroy_state(NULL, &dm_state->base);
+}
+
 static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	/* amdgpu_dm_crtc_modeset_required */
 	KUNIT_CASE(dm_test_crtc_modeset_required_active_mode_changed),
@@ -488,6 +653,18 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_crtc_set_vupdate_irq_no_otg),
 	/* idle_create_workqueue */
 	KUNIT_CASE(dm_test_idle_create_workqueue),
+	/* amdgpu_dm_crtc_set_static_screen_optimze */
+	KUNIT_CASE(dm_test_crtc_set_static_screen_optimze_no_sr_entry),
+	/* amdgpu_dm_crtc_enable_vblank */
+	KUNIT_CASE(dm_test_crtc_enable_vblank_rejects_unconfigured),
+	/* amdgpu_dm_crtc_update_crtc_active_planes */
+	KUNIT_CASE(dm_test_crtc_update_active_planes_no_stream),
+	/* amdgpu_dm_crtc_duplicate_state */
+	KUNIT_CASE(dm_test_crtc_duplicate_state_copies_fields),
+	/* amdgpu_dm_crtc_reset_state */
+	KUNIT_CASE(dm_test_crtc_reset_state_allocates_state),
+	/* amdgpu_dm_crtc_destroy_state */
+	KUNIT_CASE(dm_test_crtc_destroy_state_no_stream),
 	{}
 };
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 15/41] drm/amd/display: Add vblank handling tests for crtc
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (11 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 14/41] drm/amd/display: Add KUnit tests for more crtc functions Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 16/41] drm/amd/display: Add idle worker " Roman.Li
                   ` (26 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha

From: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>

Add KUnit coverage for the CRTC vblank paths:

- amdgpu_dm_crtc_handle_vblank: no-event completion and the
  AMDGPU_FLIP_SUBMITTED guard that keeps a pending event pending.
- amdgpu_dm_crtc_vblank_control_worker: enable increments, disable
  decrements, and disable clamps the active vblank IRQ count at zero.
- amdgpu_dm_crtc_disable_vblank: disable path returns cleanly when the
  IRQ subsystem is not installed.

Expose amdgpu_dm_crtc_vblank_control_worker for KUnit via
STATIC_IFN_KUNIT/EXPORT_IF_KUNIT and declare it in the header.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |   5 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.h    |   1 +
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 213 ++++++++++++++++++
 3 files changed, 218 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index ce42102109bb..2a4e241350f0 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -59,6 +59,7 @@ void amdgpu_dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc)
 
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 }
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_handle_vblank);
 
 bool amdgpu_dm_crtc_modeset_required(struct drm_crtc_state *crtc_state,
 			     struct dc_stream_state *new_stream,
@@ -216,7 +217,7 @@ struct idle_workqueue *idle_create_workqueue(struct amdgpu_device *adev)
 }
 EXPORT_IF_KUNIT(idle_create_workqueue);
 
-static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
+STATIC_IFN_KUNIT void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
 {
 	struct vblank_control_work *vblank_work =
 		container_of(work, struct vblank_control_work, work);
@@ -241,6 +242,7 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
 
 	kfree(vblank_work);
 }
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_vblank_control_worker);
 
 static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable)
 {
@@ -400,6 +402,7 @@ void amdgpu_dm_crtc_disable_vblank(struct drm_crtc *crtc)
 {
 	amdgpu_dm_crtc_set_vblank(crtc, false);
 }
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_disable_vblank);
 
 STATIC_IFN_KUNIT void amdgpu_dm_crtc_destroy_state(struct drm_crtc *crtc,
 				  struct drm_crtc_state *state)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
index ed6e8021d69e..c68b7b2e1916 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
@@ -52,6 +52,7 @@ struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *crtc);
 void amdgpu_dm_crtc_reset_state(struct drm_crtc *crtc);
 void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc,
 					      struct drm_crtc_state *new_crtc_state);
+void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work);
 #endif
 
 bool amdgpu_dm_crtc_vrr_active(const struct dm_crtc_state *dm_state);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index ce20692959d0..4d4b4061c789 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -9,6 +9,7 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_connector.h>
 #include <drm/drm_kunit_helpers.h>
+#include <drm/drm_vblank.h>
 
 #include "dc.h"
 #include "amdgpu.h"
@@ -621,6 +622,209 @@ static void dm_test_crtc_destroy_state_no_stream(struct kunit *test)
 	amdgpu_dm_crtc_destroy_state(NULL, &dm_state->base);
 }
 
+/**
+ * dm_test_crtc_handle_vblank_no_event - Test vblank handling with no pending event
+ * @test: The KUnit test context
+ *
+ * With no flip event pending, handling a vblank must complete without sending a
+ * vblank event and must leave acrtc->event untouched (NULL).
+ */
+static void dm_test_crtc_handle_vblank_no_event(struct kunit *test)
+{
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	/* Initialise vblank so drm_crtc_handle_vblank() runs cleanly. */
+	KUNIT_ASSERT_EQ(test, drm_vblank_init(&adev->ddev, 1), 0);
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
+	acrtc->base.dev = &adev->ddev;
+	acrtc->event = NULL;
+
+	amdgpu_dm_crtc_handle_vblank(acrtc);
+
+	KUNIT_EXPECT_NULL(test, acrtc->event);
+}
+
+/**
+ * dm_test_crtc_handle_vblank_skips_when_flip_submitted - Test event kept on submit
+ * @test: The KUnit test context
+ *
+ * A pending event whose flip is still AMDGPU_FLIP_SUBMITTED must not be signalled
+ * on vblank; acrtc->event must remain set for later completion.
+ */
+static void dm_test_crtc_handle_vblank_skips_when_flip_submitted(struct kunit *test)
+{
+	struct drm_pending_vblank_event *event;
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	KUNIT_ASSERT_EQ(test, drm_vblank_init(&adev->ddev, 1), 0);
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
+	event = kunit_kzalloc(test, sizeof(*event), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, event);
+
+	acrtc->base.dev = &adev->ddev;
+	acrtc->event = event;
+	acrtc->pflip_status = AMDGPU_FLIP_SUBMITTED;
+
+	amdgpu_dm_crtc_handle_vblank(acrtc);
+
+	/* Flip still in-flight: event must be preserved, not signalled. */
+	KUNIT_EXPECT_PTR_EQ(test, acrtc->event, event);
+}
+
+/**
+ * dm_test_vblank_control_worker_setup - Build a vblank_control_work for the worker
+ * @test: The KUnit test context
+ * @enable: Value for vblank_work->enable
+ * @count: Initial dm->active_vblank_irq_count
+ *
+ * Returns a work item wired to a freshly allocated adev/crtc/stream. The CRTC is
+ * left without an atomic state so amdgpu_dm_ism_commit_event() short-circuits and
+ * only the vblank IRQ accounting in the worker runs.
+ */
+static struct vblank_control_work *
+dm_test_vblank_control_worker_setup(struct kunit *test, bool enable,
+				    uint32_t count)
+{
+	struct dc_stream_state *stream;
+	struct vblank_control_work *work;
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	mutex_init(&adev->dm.dc_lock);
+	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
+	adev->dm.active_vblank_irq_count = count;
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
+	acrtc->base.dev = &adev->ddev;
+	acrtc->base.state = NULL;
+
+	stream = dm_kunit_alloc_stream(test, NULL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, stream);
+	/* Worker releases the stream; keep an extra ref so kunit owns the free. */
+	kref_get(&stream->refcount);
+
+	/* Worker kfree()s the work item, so it must be a plain allocation. */
+	work = kzalloc_obj(*work, GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, work);
+	work->dm = &adev->dm;
+	work->acrtc = acrtc;
+	work->stream = stream;
+	work->enable = enable;
+
+	return work;
+}
+
+/**
+ * dm_test_vblank_control_worker_enable_increments - Test enable bumps IRQ count
+ * @test: The KUnit test context
+ *
+ * Running the worker with enable set must increment the active vblank IRQ count.
+ */
+static void dm_test_vblank_control_worker_enable_increments(struct kunit *test)
+{
+	struct vblank_control_work *work;
+	struct amdgpu_display_manager *dm;
+
+	work = dm_test_vblank_control_worker_setup(test, true, 0);
+	dm = work->dm;
+
+	amdgpu_dm_crtc_vblank_control_worker(&work->work);
+
+	KUNIT_EXPECT_EQ(test, dm->active_vblank_irq_count, 1);
+}
+
+/**
+ * dm_test_vblank_control_worker_disable_decrements - Test disable drops IRQ count
+ * @test: The KUnit test context
+ *
+ * Running the worker with enable clear must decrement a non-zero active vblank
+ * IRQ count.
+ */
+static void dm_test_vblank_control_worker_disable_decrements(struct kunit *test)
+{
+	struct vblank_control_work *work;
+	struct amdgpu_display_manager *dm;
+
+	work = dm_test_vblank_control_worker_setup(test, false, 2);
+	dm = work->dm;
+
+	amdgpu_dm_crtc_vblank_control_worker(&work->work);
+
+	KUNIT_EXPECT_EQ(test, dm->active_vblank_irq_count, 1);
+}
+
+/**
+ * dm_test_vblank_control_worker_disable_clamps_zero - Test disable clamps at zero
+ * @test: The KUnit test context
+ *
+ * Disabling when the active vblank IRQ count is already zero must not underflow.
+ */
+static void dm_test_vblank_control_worker_disable_clamps_zero(struct kunit *test)
+{
+	struct vblank_control_work *work;
+	struct amdgpu_display_manager *dm;
+
+	work = dm_test_vblank_control_worker_setup(test, false, 0);
+	dm = work->dm;
+
+	amdgpu_dm_crtc_vblank_control_worker(&work->work);
+
+	KUNIT_EXPECT_EQ(test, dm->active_vblank_irq_count, 0);
+}
+
+/**
+ * dm_test_crtc_disable_vblank_no_irq_installed - Test disable with IRQ uninstalled
+ * @test: The KUnit test context
+ *
+ * Disabling vblank walks amdgpu_dm_crtc_set_vblank()'s disable path. With the
+ * IRQ subsystem not installed, amdgpu_irq_put() returns early so the routine
+ * completes without touching the vblank workqueue or the active IRQ count.
+ */
+static void dm_test_crtc_disable_vblank_no_irq_installed(struct kunit *test)
+{
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
+	/* DCE_VERSION_6_0 has no VRR, so the vupdate-irq branch is skipped. */
+	adev->dm.dc->ctx->dce_version = DCE_VERSION_6_0;
+	adev->dm.active_vblank_irq_count = 0;
+
+	/* No CRTCs registered and IRQs not installed -> irq_put returns early. */
+	adev->mode_info.num_crtc = 0;
+	adev->irq.installed = false;
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
+	acrtc->base.dev = &adev->ddev;
+	acrtc->crtc_id = 0;
+
+	amdgpu_dm_crtc_disable_vblank(&acrtc->base);
+
+	KUNIT_EXPECT_EQ(test, adev->dm.active_vblank_irq_count, 0);
+}
+
 static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	/* amdgpu_dm_crtc_modeset_required */
 	KUNIT_CASE(dm_test_crtc_modeset_required_active_mode_changed),
@@ -665,6 +869,15 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_crtc_reset_state_allocates_state),
 	/* amdgpu_dm_crtc_destroy_state */
 	KUNIT_CASE(dm_test_crtc_destroy_state_no_stream),
+	/* amdgpu_dm_crtc_handle_vblank */
+	KUNIT_CASE(dm_test_crtc_handle_vblank_no_event),
+	KUNIT_CASE(dm_test_crtc_handle_vblank_skips_when_flip_submitted),
+	/* amdgpu_dm_crtc_vblank_control_worker */
+	KUNIT_CASE(dm_test_vblank_control_worker_enable_increments),
+	KUNIT_CASE(dm_test_vblank_control_worker_disable_decrements),
+	KUNIT_CASE(dm_test_vblank_control_worker_disable_clamps_zero),
+	/* amdgpu_dm_crtc_disable_vblank */
+	KUNIT_CASE(dm_test_crtc_disable_vblank_no_irq_installed),
 	{}
 };
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 16/41] drm/amd/display: Add idle worker tests for crtc
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (12 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 15/41] drm/amd/display: Add vblank handling tests for crtc Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 17/41] drm/amd/display: Add active plane count " Roman.Li
                   ` (25 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha

From: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>

Expose amdgpu_dm_idle_worker() for KUnit and add tests covering the
disabled exit, both loop break paths, and the enable-body path. Add
dm_kunit_alloc_dc_state() and dm_kunit_alloc_clk_mgr() helpers to
support the new tests.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |   3 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.h    |   1 +
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 181 ++++++++++++++++++
 .../amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c |  29 +++
 .../tests/amdgpu_dm_kunit_test_helpers.h      |   3 +
 5 files changed, 216 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index 2a4e241350f0..fd816be907c4 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -165,7 +165,7 @@ bool amdgpu_dm_is_headless(struct amdgpu_device *adev)
 }
 EXPORT_IF_KUNIT(amdgpu_dm_is_headless);
 
-static void amdgpu_dm_idle_worker(struct work_struct *work)
+STATIC_IFN_KUNIT void amdgpu_dm_idle_worker(struct work_struct *work)
 {
 	struct idle_workqueue *idle_work;
 
@@ -199,6 +199,7 @@ static void amdgpu_dm_idle_worker(struct work_struct *work)
 	}
 	idle_work->dm->idle_workqueue->running = false;
 }
+EXPORT_IF_KUNIT(amdgpu_dm_idle_worker);
 
 struct idle_workqueue *idle_create_workqueue(struct amdgpu_device *adev)
 {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
index c68b7b2e1916..d1e2cb4efc54 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
@@ -53,6 +53,7 @@ void amdgpu_dm_crtc_reset_state(struct drm_crtc *crtc);
 void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc,
 					      struct drm_crtc_state *new_crtc_state);
 void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work);
+void amdgpu_dm_idle_worker(struct work_struct *work);
 #endif
 
 bool amdgpu_dm_crtc_vrr_active(const struct dm_crtc_state *dm_state);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index 4d4b4061c789..f5d9424171e8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -457,6 +457,182 @@ static void dm_test_idle_create_workqueue(struct kunit *test)
 	kfree(idle_work);
 }
 
+/**
+ * dm_test_idle_worker_disabled_clears_running - Test worker exits when disabled
+ * @test: The KUnit test context
+ *
+ * With the idle workqueue disabled, amdgpu_dm_idle_worker() must skip the idle
+ * optimization loop entirely and leave the shared running flag cleared.
+ */
+static void dm_test_idle_worker_disabled_clears_running(struct kunit *test)
+{
+	struct idle_workqueue *idle_work;
+	struct amdgpu_device *adev;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	idle_work = kunit_kzalloc(test, sizeof(*idle_work), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, idle_work);
+
+	idle_work->dm = &adev->dm;
+	idle_work->enable = false;
+	idle_work->running = true;
+	/* The worker toggles running through dm->idle_workqueue. */
+	adev->dm.idle_workqueue = idle_work;
+
+	amdgpu_dm_idle_worker(&idle_work->work);
+
+	KUNIT_EXPECT_FALSE(test, idle_work->running);
+}
+
+/**
+ * dm_test_idle_worker_enabled_breaks_when_idle_disallowed - Test loop entry/exit
+ * @test: The KUnit test context
+ *
+ * With the workqueue enabled but idle optimizations disallowed, the worker enters
+ * the detection loop once, takes the early break, and clears the running flag.
+ */
+static void dm_test_idle_worker_enabled_breaks_when_idle_disallowed(struct kunit *test)
+{
+	struct idle_workqueue *idle_work;
+	struct amdgpu_device *adev;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	mutex_init(&adev->dm.dc_lock);
+	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
+	/* First loop iteration breaks before any dc_allow_idle_optimizations(). */
+	adev->dm.dc->idle_optimizations_allowed = false;
+
+	idle_work = kunit_kzalloc(test, sizeof(*idle_work), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, idle_work);
+
+	idle_work->dm = &adev->dm;
+	idle_work->enable = true;
+	adev->dm.idle_workqueue = idle_work;
+
+	amdgpu_dm_idle_worker(&idle_work->work);
+
+	KUNIT_EXPECT_FALSE(test, idle_work->running);
+}
+
+/**
+ * dm_test_idle_worker_enabled_breaks_when_not_headless - Test second break path
+ * @test: The KUnit test context
+ *
+ * With idle optimizations allowed, the worker passes the first branch and runs
+ * dc_allow_idle_optimizations(). A connected display makes the device non-headless
+ * while no PSR is active, so the worker takes the second break and stops running.
+ */
+static void dm_test_idle_worker_enabled_breaks_when_not_headless(struct kunit *test)
+{
+	struct idle_workqueue *idle_work;
+	struct drm_connector *display;
+	struct amdgpu_device *adev;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	mutex_init(&adev->dm.dc_lock);
+	adev->dm.adev = adev;
+	adev->dm.ddev = dm_kunit_alloc_drm_with_connector_list(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.ddev);
+
+	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
+	/* Allow idle so the first branch is skipped and dc_allow() is exercised. */
+	adev->dm.dc->idle_optimizations_allowed = true;
+	/* is_apu path avoids DC_LOG_DC()'s NULL-logger dereference. */
+	adev->dm.dc->caps.is_apu = true;
+	/* Empty stream list -> amdgpu_dm_psr_is_active_allowed() returns false. */
+	adev->dm.dc->current_state = dm_kunit_alloc_dc_state(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc->current_state);
+
+	/* A connected display makes amdgpu_dm_is_headless() false. */
+	display = kunit_kzalloc(test, sizeof(*display), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, display);
+	dm_test_add_connector(adev->dm.ddev, display, DRM_MODE_CONNECTOR_HDMIA,
+			      connector_status_connected);
+
+	idle_work = kunit_kzalloc(test, sizeof(*idle_work), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, idle_work);
+	idle_work->dm = &adev->dm;
+	idle_work->enable = true;
+	adev->dm.idle_workqueue = idle_work;
+
+	amdgpu_dm_idle_worker(&idle_work->work);
+
+	KUNIT_EXPECT_FALSE(test, idle_work->running);
+}
+
+/*
+ * Report success only when disabling idle. dc_allow_idle_optimizations() then
+ * clears dc->idle_optimizations_allowed on the disable call but leaves it clear
+ * on the re-enable call inside the worker's enable-body, so the next loop
+ * iteration breaks at the first branch instead of looping forever.
+ */
+static bool dm_test_idle_apply_flip(struct dc *dc, bool enable)
+{
+	return !enable;
+}
+
+/**
+ * dm_test_idle_worker_enabled_runs_body - Test the enable-body path
+ * @test: The KUnit test context
+ *
+ * A headless device makes the second branch false so the worker runs the
+ * enable-body (dc_post_update_surfaces_to_stream() + re-enable). An injected
+ * hwss.apply_idle_power_optimizations() callback lets dc_allow_idle_optimizations()
+ * clear idle_optimizations_allowed on the disable half, so the following loop
+ * iteration breaks at the first branch and the worker stops.
+ */
+static void dm_test_idle_worker_enabled_runs_body(struct kunit *test)
+{
+	struct idle_workqueue *idle_work;
+	struct amdgpu_device *adev;
+	struct dal_logger *logger;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	mutex_init(&adev->dm.dc_lock);
+	adev->dm.adev = adev;
+	/* Empty connector list keeps the device headless -> second branch false. */
+	adev->dm.ddev = dm_kunit_alloc_drm_with_connector_list(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.ddev);
+
+	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
+	/* Allow idle so the first branch is skipped and dc_allow() is exercised. */
+	adev->dm.dc->idle_optimizations_allowed = true;
+	/* is_apu path avoids DC_LOG_DC()'s NULL-logger dereference. */
+	adev->dm.dc->caps.is_apu = true;
+	/* dc_allow() logs via DC_LOG_DEBUG() when it flips the flag. */
+	logger = kunit_kzalloc(test, sizeof(*logger), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, logger);
+	logger->dev = &adev->ddev;
+	adev->dm.dc->ctx->logger = logger;
+	/* dc_allow() only flips the flag when clk_mgr and apply() are present. */
+	adev->dm.dc->clk_mgr = dm_kunit_alloc_clk_mgr(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc->clk_mgr);
+	adev->dm.dc->hwss.apply_idle_power_optimizations = dm_test_idle_apply_flip;
+
+	idle_work = kunit_kzalloc(test, sizeof(*idle_work), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, idle_work);
+	idle_work->dm = &adev->dm;
+	idle_work->enable = true;
+	adev->dm.idle_workqueue = idle_work;
+
+	amdgpu_dm_idle_worker(&idle_work->work);
+
+	/* Enable-body ran, then the next iteration disabled idle and stopped. */
+	KUNIT_EXPECT_FALSE(test, adev->dm.dc->idle_optimizations_allowed);
+	KUNIT_EXPECT_FALSE(test, idle_work->running);
+}
+
 /* Tests for amdgpu_dm_crtc_set_static_screen_optimze() */
 
 /**
@@ -857,6 +1033,11 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_crtc_set_vupdate_irq_no_otg),
 	/* idle_create_workqueue */
 	KUNIT_CASE(dm_test_idle_create_workqueue),
+	/* amdgpu_dm_idle_worker */
+	KUNIT_CASE(dm_test_idle_worker_disabled_clears_running),
+	KUNIT_CASE(dm_test_idle_worker_enabled_breaks_when_idle_disallowed),
+	KUNIT_CASE(dm_test_idle_worker_enabled_breaks_when_not_headless),
+	KUNIT_CASE(dm_test_idle_worker_enabled_runs_body),
 	/* amdgpu_dm_crtc_set_static_screen_optimze */
 	KUNIT_CASE(dm_test_crtc_set_static_screen_optimze_no_sr_entry),
 	/* amdgpu_dm_crtc_enable_vblank */
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c
index 862ada873fbb..aad122c7229f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c
@@ -12,6 +12,7 @@
 
 #include "dc.h"
 #include "core_types.h"
+#include "clk_mgr.h"
 #include "amdgpu.h"
 #include "amdgpu_mode.h"
 #include "amdgpu_dm.h"
@@ -114,6 +115,34 @@ struct dc_stream_state *dm_kunit_alloc_stream(struct kunit *test,
 }
 EXPORT_SYMBOL(dm_kunit_alloc_stream);
 
+struct dc_state *dm_kunit_alloc_dc_state(struct kunit *test)
+{
+	struct dc_state *state;
+
+	state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, state);
+
+	return state;
+}
+EXPORT_SYMBOL(dm_kunit_alloc_dc_state);
+
+struct clk_mgr *dm_kunit_alloc_clk_mgr(struct kunit *test)
+{
+	struct clk_mgr *clk_mgr;
+	struct clk_mgr_funcs *funcs;
+
+	clk_mgr = kunit_kzalloc(test, sizeof(*clk_mgr), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, clk_mgr);
+
+	funcs = kunit_kzalloc(test, sizeof(*funcs), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_NULL(test, funcs);
+
+	clk_mgr->funcs = funcs;
+
+	return clk_mgr;
+}
+EXPORT_SYMBOL(dm_kunit_alloc_clk_mgr);
+
 void dm_kunit_add_stream_to_state(struct kunit *test, struct dc_state *state,
 				  unsigned int index, struct dc_link *link)
 {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_kunit_test_helpers.h b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_kunit_test_helpers.h
index 49b358681d60..7d7bcd321775 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_kunit_test_helpers.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_kunit_test_helpers.h
@@ -13,6 +13,7 @@
 struct amdgpu_device;
 struct amdgpu_display_manager;
 struct amdgpu_dm_connector;
+struct clk_mgr;
 struct dc;
 struct dc_link;
 struct dc_state;
@@ -25,6 +26,8 @@ struct dc_link *dm_kunit_alloc_link(struct kunit *test);
 struct dc_link *dm_kunit_alloc_link_with_ctx(struct kunit *test);
 struct amdgpu_display_manager *dm_kunit_alloc_dm(struct kunit *test);
 struct drm_device *dm_kunit_alloc_drm_with_connector_list(struct kunit *test);
+struct dc_state *dm_kunit_alloc_dc_state(struct kunit *test);
+struct clk_mgr *dm_kunit_alloc_clk_mgr(struct kunit *test);
 struct dc_stream_state *dm_kunit_alloc_stream(struct kunit *test,
 					      struct dc_link *link);
 void dm_kunit_add_stream_to_state(struct kunit *test, struct dc_state *state,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 17/41] drm/amd/display: Add active plane count tests for crtc
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (13 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 16/41] drm/amd/display: Add idle worker " Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 18/41] drm/amd/display: Add KUnit test for crtc vblank event completion Roman.Li
                   ` (24 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha

From: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>

Expose amdgpu_dm_crtc_count_crtc_active_planes() for KUnit and add tests
covering the empty plane list and the mixed case exercising the mask
filter, cursor skip, missing plane state, and framebuffer presence
branches.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |   3 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.h    |   1 +
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 115 ++++++++++++++++++
 3 files changed, 118 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index fd816be907c4..82a30097072e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -587,7 +587,7 @@ static void amdgpu_dm_crtc_helper_disable(struct drm_crtc *crtc)
 {
 }
 
-static int amdgpu_dm_crtc_count_crtc_active_planes(struct drm_crtc_state *new_crtc_state)
+STATIC_IFN_KUNIT int amdgpu_dm_crtc_count_crtc_active_planes(struct drm_crtc_state *new_crtc_state)
 {
 	struct drm_atomic_commit *state = new_crtc_state->state;
 	struct drm_plane *plane;
@@ -618,6 +618,7 @@ static int amdgpu_dm_crtc_count_crtc_active_planes(struct drm_crtc_state *new_cr
 
 	return num_active;
 }
+EXPORT_IF_KUNIT(amdgpu_dm_crtc_count_crtc_active_planes);
 
 STATIC_IFN_KUNIT void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc,
 						     struct drm_crtc_state *new_crtc_state)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
index d1e2cb4efc54..93c6d0d8d7fd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h
@@ -50,6 +50,7 @@ void amdgpu_dm_crtc_destroy_state(struct drm_crtc *crtc,
 				  struct drm_crtc_state *state);
 struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *crtc);
 void amdgpu_dm_crtc_reset_state(struct drm_crtc *crtc);
+int amdgpu_dm_crtc_count_crtc_active_planes(struct drm_crtc_state *new_crtc_state);
 void amdgpu_dm_crtc_update_crtc_active_planes(struct drm_crtc *crtc,
 					      struct drm_crtc_state *new_crtc_state);
 void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index f5d9424171e8..9948d1780454 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -706,6 +706,118 @@ static void dm_test_crtc_update_active_planes_no_stream(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, dm_state->active_planes, 0);
 }
 
+/* Tests for amdgpu_dm_crtc_count_crtc_active_planes() */
+
+static void dm_test_add_plane(struct drm_device *dev, struct drm_plane *plane,
+			      unsigned int index, enum drm_plane_type type)
+{
+	INIT_LIST_HEAD(&plane->head);
+	plane->index = index;
+	plane->type = type;
+	list_add_tail(&plane->head, &dev->mode_config.plane_list);
+}
+
+/**
+ * dm_test_count_crtc_active_planes_none - Test empty plane list counts zero
+ * @test: The KUnit test context
+ *
+ * With no planes attached to the CRTC the active plane count must be zero.
+ */
+static void dm_test_count_crtc_active_planes_none(struct kunit *test)
+{
+	struct drm_crtc_state *crtc_state;
+	struct drm_atomic_commit *state;
+	struct drm_device *dev;
+
+	dev = dm_kunit_alloc_drm_with_connector_list(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+	INIT_LIST_HEAD(&dev->mode_config.plane_list);
+
+	state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+	state->dev = dev;
+
+	crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
+	crtc_state->state = state;
+	crtc_state->plane_mask = 0;
+
+	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_count_crtc_active_planes(crtc_state), 0);
+}
+
+/**
+ * dm_test_count_crtc_active_planes_mixed - Test counting across all plane cases
+ * @test: The KUnit test context
+ *
+ * Exercises every branch of the counting loop: a plane excluded by the mask,
+ * a cursor plane (skipped), a masked plane with no new state (counted), a
+ * masked plane with a framebuffer (counted) and a masked plane without a
+ * framebuffer (not counted). Only two planes should be reported active.
+ */
+static void dm_test_count_crtc_active_planes_mixed(struct kunit *test)
+{
+	struct drm_plane *plane_no_state;
+	struct drm_plane *plane_cursor;
+	struct drm_plane *plane_with_fb;
+	struct drm_plane *plane_no_fb;
+	struct drm_plane *plane_excluded;
+	struct drm_plane_state *ps_fb;
+	struct drm_plane_state *ps_no_fb;
+	struct drm_crtc_state *crtc_state;
+	struct drm_atomic_commit *state;
+	struct drm_framebuffer *fb;
+	struct drm_device *dev;
+
+	dev = dm_kunit_alloc_drm_with_connector_list(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+	INIT_LIST_HEAD(&dev->mode_config.plane_list);
+
+	plane_no_state = kunit_kzalloc(test, sizeof(*plane_no_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_no_state);
+	plane_cursor = kunit_kzalloc(test, sizeof(*plane_cursor), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_cursor);
+	plane_with_fb = kunit_kzalloc(test, sizeof(*plane_with_fb), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_with_fb);
+	plane_no_fb = kunit_kzalloc(test, sizeof(*plane_no_fb), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_no_fb);
+	plane_excluded = kunit_kzalloc(test, sizeof(*plane_excluded), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, plane_excluded);
+
+	dm_test_add_plane(dev, plane_no_state, 0, DRM_PLANE_TYPE_PRIMARY);
+	dm_test_add_plane(dev, plane_cursor, 1, DRM_PLANE_TYPE_CURSOR);
+	dm_test_add_plane(dev, plane_with_fb, 2, DRM_PLANE_TYPE_PRIMARY);
+	dm_test_add_plane(dev, plane_no_fb, 3, DRM_PLANE_TYPE_PRIMARY);
+	dm_test_add_plane(dev, plane_excluded, 4, DRM_PLANE_TYPE_PRIMARY);
+
+	fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fb);
+	ps_fb = kunit_kzalloc(test, sizeof(*ps_fb), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ps_fb);
+	ps_fb->fb = fb;
+	ps_no_fb = kunit_kzalloc(test, sizeof(*ps_no_fb), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ps_no_fb);
+	ps_no_fb->fb = NULL;
+
+	state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+	state->dev = dev;
+	state->planes = kunit_kzalloc(test, sizeof(*state->planes) * 5, GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state->planes);
+	state->planes[0].new_state = NULL;
+	state->planes[1].new_state = ps_fb;
+	state->planes[2].new_state = ps_fb;
+	state->planes[3].new_state = ps_no_fb;
+	state->planes[4].new_state = ps_fb;
+
+	crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
+	crtc_state->state = state;
+	/* Exclude plane index 4 from the CRTC. */
+	crtc_state->plane_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3);
+
+	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_count_crtc_active_planes(crtc_state), 2);
+}
+
 /* Tests for amdgpu_dm_crtc_duplicate_state() */
 
 /**
@@ -1044,6 +1156,9 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_crtc_enable_vblank_rejects_unconfigured),
 	/* amdgpu_dm_crtc_update_crtc_active_planes */
 	KUNIT_CASE(dm_test_crtc_update_active_planes_no_stream),
+	/* amdgpu_dm_crtc_count_crtc_active_planes */
+	KUNIT_CASE(dm_test_count_crtc_active_planes_none),
+	KUNIT_CASE(dm_test_count_crtc_active_planes_mixed),
 	/* amdgpu_dm_crtc_duplicate_state */
 	KUNIT_CASE(dm_test_crtc_duplicate_state_copies_fields),
 	/* amdgpu_dm_crtc_reset_state */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 18/41] drm/amd/display: Add KUnit test for crtc vblank event completion
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (14 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 17/41] drm/amd/display: Add active plane count " Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 19/41] drm/amd/display: Add KUnit tests for crtc set_vupdate_irq Roman.Li
                   ` (23 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha

From: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>

Add dm_test_crtc_handle_vblank_completes_cursor_only to cover the
previously untested branch in amdgpu_dm_crtc_handle_vblank() where a
pending event with pflip_status != AMDGPU_FLIP_SUBMITTED (a cursor-only
commit) is signalled: the vblank event is sent, the vblank reference is
dropped, and acrtc->event is cleared.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 45 +++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index 9948d1780454..6bc4f932c839 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -971,6 +971,50 @@ static void dm_test_crtc_handle_vblank_skips_when_flip_submitted(struct kunit *t
 	KUNIT_EXPECT_PTR_EQ(test, acrtc->event, event);
 }
 
+/**
+ * dm_test_crtc_handle_vblank_completes_cursor_only - Test event sent on vblank
+ * @test: The KUnit test context
+ *
+ * A pending event whose flip is not AMDGPU_FLIP_SUBMITTED (a cursor-only commit)
+ * must be signalled on vblank: the vblank event is sent, the vblank reference is
+ * dropped and acrtc->event is cleared.
+ */
+static void dm_test_crtc_handle_vblank_completes_cursor_only(struct kunit *test)
+{
+	struct drm_pending_vblank_event *event;
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	KUNIT_ASSERT_EQ(test, drm_vblank_init(&adev->ddev, 1), 0);
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
+
+	/* drm_crtc_send_vblank_event() consumes (kfree()s) the event. */
+	event = kzalloc_obj(*event, GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, event);
+
+	acrtc->base.dev = &adev->ddev;
+	acrtc->event = event;
+	acrtc->pflip_status = AMDGPU_FLIP_NONE;
+
+	/*
+	 * Take a vblank reference so the handler's drm_crtc_vblank_put() does not
+	 * underflow. Mark vblank enabled so the get succeeds without a hardware
+	 * enable hook.
+	 */
+	adev->ddev.vblank[0].enabled = true;
+	KUNIT_ASSERT_EQ(test, drm_crtc_vblank_get(&acrtc->base), 0);
+
+	amdgpu_dm_crtc_handle_vblank(acrtc);
+
+	/* Cursor-only commit: event was signalled and cleared. */
+	KUNIT_EXPECT_NULL(test, acrtc->event);
+}
+
 /**
  * dm_test_vblank_control_worker_setup - Build a vblank_control_work for the worker
  * @test: The KUnit test context
@@ -1168,6 +1212,7 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	/* amdgpu_dm_crtc_handle_vblank */
 	KUNIT_CASE(dm_test_crtc_handle_vblank_no_event),
 	KUNIT_CASE(dm_test_crtc_handle_vblank_skips_when_flip_submitted),
+	KUNIT_CASE(dm_test_crtc_handle_vblank_completes_cursor_only),
 	/* amdgpu_dm_crtc_vblank_control_worker */
 	KUNIT_CASE(dm_test_vblank_control_worker_enable_increments),
 	KUNIT_CASE(dm_test_vblank_control_worker_disable_decrements),
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 19/41] drm/amd/display: Add KUnit tests for crtc set_vupdate_irq
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (15 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 18/41] drm/amd/display: Add KUnit test for crtc vblank event completion Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 20/41] drm/amd/display: Add KUnit tests for crtc set_static_screen_optimze Roman.Li
                   ` (22 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha

From: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>

Add dm_test_crtc_set_vupdate_irq_dc_busy and
dm_test_crtc_set_vupdate_irq_enable to cover the previously untested
paths in amdgpu_dm_crtc_set_vupdate_irq() where an OTG instance is
assigned: dc_interrupt_set() failing (returns -EBUSY) and succeeding
via a mock IRQ service (returns 0 for enable and disable).

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 99 +++++++++++++++++++
 1 file changed, 99 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index 6bc4f932c839..db98e42c561b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -12,6 +12,8 @@
 #include <drm/drm_vblank.h>
 
 #include "dc.h"
+#include "inc/core_types.h"
+#include "irq/irq_service.h"
 #include "amdgpu.h"
 #include "amdgpu_mode.h"
 #include "amdgpu_dm.h"
@@ -430,6 +432,101 @@ static void dm_test_crtc_set_vupdate_irq_no_otg(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, false), 0);
 }
 
+/**
+ * dm_test_crtc_set_vupdate_irq_dc_busy - Test vupdate irq when DC rejects request
+ * @test: The KUnit test context
+ *
+ * With an OTG instance assigned but no DC attached, dc_interrupt_set() returns
+ * false and the function must report the request as busy (-EBUSY).
+ */
+static void dm_test_crtc_set_vupdate_irq_dc_busy(struct kunit *test)
+{
+	struct amdgpu_crtc *acrtc;
+	struct amdgpu_device *adev;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
+
+	acrtc->base.dev = &adev->ddev;
+	acrtc->otg_inst = 0;
+
+	/* adev->dm.dc is NULL, so dc_interrupt_set() returns false. */
+	KUNIT_EXPECT_EQ(test,
+			amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, true), -EBUSY);
+}
+
+/* Per-source funcs let dc_interrupt_set() succeed without register access. */
+static bool dm_test_vupdate_irq_src_set(struct irq_service *irq_service,
+					const struct irq_source_info *info,
+					bool enable)
+{
+	return true;
+}
+
+static bool dm_test_vupdate_irq_src_ack(struct irq_service *irq_service,
+					const struct irq_source_info *info)
+{
+	return true;
+}
+
+static struct irq_source_info_funcs dm_test_vupdate_irq_src_funcs = {
+	.set = dm_test_vupdate_irq_src_set,
+	.ack = dm_test_vupdate_irq_src_ack,
+};
+
+/**
+ * dm_test_crtc_set_vupdate_irq_enable - Test vupdate irq enable/disable success
+ * @test: The KUnit test context
+ *
+ * With an OTG instance assigned and a DC whose IRQ service accepts the request,
+ * enabling and disabling the vupdate IRQ must both succeed (return 0).
+ */
+static void dm_test_crtc_set_vupdate_irq_enable(struct kunit *test)
+{
+	struct irq_source_info *info;
+	struct resource_pool *res_pool;
+	struct irq_service *irqs;
+	struct amdgpu_crtc *acrtc;
+	struct amdgpu_device *adev;
+	struct dc *dc;
+	int i;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
+
+	dc = dm_kunit_alloc_dc_with_ctx(test);
+	res_pool = kunit_kzalloc(test, sizeof(*res_pool), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res_pool);
+	irqs = kunit_kzalloc(test, sizeof(*irqs), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, irqs);
+
+	/* Populate the per-source info table so dc_interrupt_set() succeeds. */
+	info = kunit_kzalloc(test, sizeof(*info) * DAL_IRQ_SOURCES_NUMBER,
+			     GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, info);
+	for (i = 0; i < DAL_IRQ_SOURCES_NUMBER; i++)
+		info[i].funcs = &dm_test_vupdate_irq_src_funcs;
+
+	irqs->info = info;
+	res_pool->irqs = irqs;
+	dc->res_pool = res_pool;
+	adev->dm.dc = dc;
+
+	acrtc->base.dev = &adev->ddev;
+	acrtc->otg_inst = 0;
+
+	KUNIT_EXPECT_EQ(test,
+			amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, true), 0);
+	KUNIT_EXPECT_EQ(test,
+			amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, false), 0);
+}
+
 /* Tests for idle_create_workqueue() */
 
 /**
@@ -1187,6 +1284,8 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_crtc_helper_mode_fixup_returns_true),
 	/* amdgpu_dm_crtc_set_vupdate_irq */
 	KUNIT_CASE(dm_test_crtc_set_vupdate_irq_no_otg),
+	KUNIT_CASE(dm_test_crtc_set_vupdate_irq_dc_busy),
+	KUNIT_CASE(dm_test_crtc_set_vupdate_irq_enable),
 	/* idle_create_workqueue */
 	KUNIT_CASE(dm_test_idle_create_workqueue),
 	/* amdgpu_dm_idle_worker */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 20/41] drm/amd/display: Add KUnit tests for crtc set_static_screen_optimze
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (16 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 19/41] drm/amd/display: Add KUnit tests for crtc set_vupdate_irq Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 21/41] drm/amd/display: Refactor stream validation Roman.Li
                   ` (21 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha

From: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>

Add dm_test_crtc_set_static_screen_optimze_sr_entry_psr and
dm_test_crtc_set_static_screen_optimze_psr_su_skips to cover the
allow_sr_entry == true path of amdgpu_dm_crtc_set_static_screen_optimze():
the replay/PSR event updates when psr_version < DC_PSR_VERSION_SU_1, and
skipping the PSR event update when psr_version is DC_PSR_VERSION_SU_1.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 55 +++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index db98e42c561b..fa4986153eda 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -756,6 +756,59 @@ static void dm_test_crtc_set_static_screen_optimze_no_sr_entry(struct kunit *tes
 	amdgpu_dm_crtc_set_static_screen_optimze(dm, stream, false, false);
 }
 
+/**
+ * dm_test_crtc_set_static_screen_optimze_sr_entry_psr - Test SSO toggle drives PSR
+ * @test: The KUnit test context
+ *
+ * With self-refresh entry allowed and a PSR version below DC_PSR_VERSION_SU_1,
+ * the function must run both the replay and PSR event updates. The link has no
+ * replay/PSR feature enabled, so both event helpers short-circuit safely. Both
+ * SSO states are exercised to cover the set_vsync_event computation.
+ */
+static void dm_test_crtc_set_static_screen_optimze_sr_entry_psr(struct kunit *test)
+{
+	struct amdgpu_display_manager *dm;
+	struct dc_link *link;
+	struct dc_stream_state *stream;
+
+	dm = kunit_kzalloc(test, sizeof(*dm), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm);
+
+	link = dm_kunit_alloc_link(test);
+	stream = dm_kunit_alloc_stream(test, link);
+
+	/* psr_version < DC_PSR_VERSION_SU_1 -> PSR event branch is taken. */
+	link->psr_settings.psr_version = DC_PSR_VERSION_1;
+
+	amdgpu_dm_crtc_set_static_screen_optimze(dm, stream, true, true);
+	amdgpu_dm_crtc_set_static_screen_optimze(dm, stream, false, true);
+}
+
+/**
+ * dm_test_crtc_set_static_screen_optimze_psr_su_skips - Test PSR SU skips PSR event
+ * @test: The KUnit test context
+ *
+ * With self-refresh entry allowed and a PSR version of DC_PSR_VERSION_SU_1, the
+ * function must update the replay event but skip the PSR event update.
+ */
+static void dm_test_crtc_set_static_screen_optimze_psr_su_skips(struct kunit *test)
+{
+	struct amdgpu_display_manager *dm;
+	struct dc_link *link;
+	struct dc_stream_state *stream;
+
+	dm = kunit_kzalloc(test, sizeof(*dm), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm);
+
+	link = dm_kunit_alloc_link(test);
+	stream = dm_kunit_alloc_stream(test, link);
+
+	/* psr_version >= DC_PSR_VERSION_SU_1 -> PSR event branch is skipped. */
+	link->psr_settings.psr_version = DC_PSR_VERSION_SU_1;
+
+	amdgpu_dm_crtc_set_static_screen_optimze(dm, stream, true, true);
+}
+
 /* Tests for amdgpu_dm_crtc_enable_vblank() */
 
 /**
@@ -1295,6 +1348,8 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_idle_worker_enabled_runs_body),
 	/* amdgpu_dm_crtc_set_static_screen_optimze */
 	KUNIT_CASE(dm_test_crtc_set_static_screen_optimze_no_sr_entry),
+	KUNIT_CASE(dm_test_crtc_set_static_screen_optimze_sr_entry_psr),
+	KUNIT_CASE(dm_test_crtc_set_static_screen_optimze_psr_su_skips),
 	/* amdgpu_dm_crtc_enable_vblank */
 	KUNIT_CASE(dm_test_crtc_enable_vblank_rejects_unconfigured),
 	/* amdgpu_dm_crtc_update_crtc_active_planes */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 21/41] drm/amd/display: Refactor stream validation
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (17 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 20/41] drm/amd/display: Add KUnit tests for crtc set_static_screen_optimze Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 22/41] drm/amd/display: Unify force_yuv debugfs into force_yuv_pixel_format Roman.Li
                   ` (20 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen

From: Ivan Lipski <ivan.lipski@amd.com>

[Why]
amdgpu_dm_create_validate_stream_for_sink() drove its RGB -> YUV422 ->
YUV420 chroma fallback by recursing and toggling the shared
aconnector->force_yuv420_output / force_yuv422_output fields, resetting
them after each recursive call. Those fields have no locking and the
function runs concurrently on the same connector from two paths: the
connector probe worker (->mode_valid) and a compositor's atomic check
(dm_update_crtc_state). When both run at once, one thread can clear the
override just before the other tests its exit condition, so the exit is
missed and validation loops indefinitely, hanging the modeset path.

[How]
- Replace the recursion with an explicit loop over the chroma encodings
  wrapping the existing bpc walk.
- Carry the encoding/bpc selection on the stack, passed by value into
  create_stream_for_sink() / fill_stream_properties_from_drm_display_mode(),
  instead of mutating shared connector state.
- Derive the supported encodings and bit depths into bitmaps and drive
  validation from them, gating each candidate on the sink's advertised
  capability so unsupported encodings are never retried.
- Move encoding selection entirely to the caller and pass the chosen
  dc_pixel_encoding into fill_stream_properties_from_drm_display_mode().

Assisted-by: Copilot:claude-opus-4.8
Reviewed-by: Jerry Zuo <jerry.zuo@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../display/amdgpu_dm/amdgpu_dm_connector.c   | 280 ++++++++++++------
 .../display/amdgpu_dm/amdgpu_dm_connector.h   |   8 +-
 2 files changed, 189 insertions(+), 99 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
index e637db2723c1..825c3408763c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
@@ -855,7 +855,9 @@ STATIC_IFN_KUNIT void fill_stream_properties_from_drm_display_mode(
 	const struct drm_connector *connector,
 	const struct drm_connector_state *connector_state,
 	const struct dc_stream_state *old_stream,
-	int requested_bpc)
+	int requested_bpc,
+	enum dc_pixel_encoding requested_encoding,
+	bool is_hdmi_ep)
 {
 	struct dc_crtc_timing *timing_out = &stream->timing;
 	const struct drm_display_info *info = &connector->display_info;
@@ -874,26 +876,14 @@ STATIC_IFN_KUNIT void fill_stream_properties_from_drm_display_mode(
 	timing_out->h_border_right = 0;
 	timing_out->v_border_top = 0;
 	timing_out->v_border_bottom = 0;
-	/* TODO: un-hardcode */
-	if (drm_mode_is_420_only(info, mode_in) ||
-	    (aconnector &&
-	     (aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR420 ||
-	      aconnector->force_yuv420_output) &&
-	     drm_mode_is_420_also(info, mode_in)))
-		timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
-	else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
-			&& aconnector
-			&& (aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR422
-			|| aconnector->force_yuv422_output))
-		timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR422;
-	else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
-			&& (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
-			    stream->signal == SIGNAL_TYPE_HDMI_FRL)
-			&& aconnector
-			&& aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR444)
-		timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
-	else
-		timing_out->pixel_encoding = PIXEL_ENCODING_RGB;
+
+	/*
+	 * The pixel encoding to use is decided entirely by the caller (see
+	 * amdgpu_dm_create_validate_stream_for_sink()), which enumerates only
+	 * the encodings the sink actually advertises. This helper must not
+	 * second-guess that choice; it simply applies it.
+	 */
+	timing_out->pixel_encoding = requested_encoding;
 
 	timing_out->timing_3d_format = TIMING_3D_FORMAT_NONE;
 	timing_out->display_color_depth = amdgpu_dm_convert_color_depth_from_display_info(
@@ -959,14 +949,15 @@ STATIC_IFN_KUNIT void fill_stream_properties_from_drm_display_mode(
 
 	stream->out_transfer_func.type = TF_TYPE_PREDEFINED;
 	stream->out_transfer_func.tf = TRANSFER_FUNCTION_SRGB;
-	if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
-		if (!adjust_colour_depth_from_display_info(timing_out, info) &&
-		    drm_mode_is_420_also(info, mode_in) &&
-		    timing_out->pixel_encoding != PIXEL_ENCODING_YCBCR420) {
-			timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
-			adjust_colour_depth_from_display_info(timing_out, info);
-		}
-	}
+
+	/* Clamp the HDMI colour depth to what the sink's max TMDS clock
+	 * allows. The pixel encoding is fixed by the caller and must not be
+	 * changed here: the caller already enumerates YCbCr420 as its own
+	 * candidate, so silently switching to it would hide an enumeration
+	 * bug and produce a stream the caller never asked to validate.
+	 */
+	if (is_hdmi_ep)
+		adjust_colour_depth_from_display_info(timing_out, info);
 
 	stream->output_color_space = amdgpu_dm_get_output_color_space(timing_out, connector_state);
 	stream->content_type = get_output_content_type(connector_state);
@@ -1433,7 +1424,9 @@ create_stream_for_sink(struct drm_connector *connector,
 		       const struct drm_display_mode *drm_mode,
 		       const struct dm_connector_state *dm_state,
 		       const struct dc_stream_state *old_stream,
-		       int requested_bpc)
+		       int requested_bpc,
+		       enum dc_pixel_encoding requested_encoding,
+		       bool is_hdmi_ep)
 {
 	struct drm_device *dev = connector->dev;
 	struct amdgpu_dm_connector *aconnector = NULL;
@@ -1544,11 +1537,11 @@ create_stream_for_sink(struct drm_connector *connector,
 	if (!scale || mode_refresh != preferred_refresh)
 		fill_stream_properties_from_drm_display_mode(
 			stream, &mode, connector, con_state, NULL,
-			requested_bpc);
+			requested_bpc, requested_encoding, is_hdmi_ep);
 	else
 		fill_stream_properties_from_drm_display_mode(
 			stream, &mode, connector, con_state, old_stream,
-			requested_bpc);
+			requested_bpc, requested_encoding, is_hdmi_ep);
 
 	/* The rest isn't needed for writeback connectors */
 	if (!aconnector)
@@ -2221,13 +2214,31 @@ amdgpu_dm_create_validate_stream_for_sink(struct drm_connector *connector,
 					  const struct dm_connector_state *dm_state,
 					  const struct dc_stream_state *old_stream)
 {
+	/*
+	 * Ordered lists of the encodings and bit depths we are willing to
+	 * validate, best quality/bandwidth first. The per-sink masks built
+	 * below gate which of these entries are actually attempted.
+	 */
+	static const enum dc_pixel_encoding encoding_order[] = {
+		PIXEL_ENCODING_YCBCR444,
+		PIXEL_ENCODING_RGB,
+		PIXEL_ENCODING_YCBCR422,
+		PIXEL_ENCODING_YCBCR420,
+	};
+	static const u8 bpc_order[] = { 16, 12, 10, 8, 6 };
+
 	struct amdgpu_dm_connector *aconnector = NULL;
 	struct amdgpu_device *adev = drm_to_adev(connector->dev);
-	struct dc_stream_state *stream;
+	const struct drm_display_info *info = &connector->display_info;
+	struct dc_stream_state *stream = NULL;
 	const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL;
 	int requested_bpc = drm_state ? drm_state->max_requested_bpc : 8;
 	enum dc_status dc_result = DC_OK;
-	uint8_t bpc_limit = 6;
+	enum signal_type signal = SIGNAL_TYPE_NONE;
+	u32 encoding_mask = 0;
+	u32 bpc_mask = 0;
+	bool is_hdmi_ep = false;
+	unsigned int i, j;
 
 	if (!dm_state)
 		return NULL;
@@ -2235,87 +2246,162 @@ amdgpu_dm_create_validate_stream_for_sink(struct drm_connector *connector,
 	if (connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK)
 		aconnector = to_amdgpu_dm_connector(connector);
 
-	if (aconnector &&
-	    (aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_TYPE_A ||
-	     aconnector->dc_link->connector_signal == SIGNAL_TYPE_HDMI_FRL ||
-	     aconnector->dc_link->dpcd_caps.dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER))
-		bpc_limit = 8;
-
-	do {
-		drm_dbg_kms(connector->dev, "Trying with %d bpc\n", requested_bpc);
-		stream = create_stream_for_sink(connector, drm_mode,
-						dm_state, old_stream,
-						requested_bpc);
-		if (stream == NULL) {
+	/*
+	 * Writeback connectors have no sink EDID to enumerate against. They
+	 * only ever use RGB at the requested depth, so build and validate a
+	 * single stream directly and return it (dc_validate_stream() is not
+	 * meaningful for the writeback path).
+	 */
+	if (!aconnector) {
+		stream = create_stream_for_sink(connector, drm_mode, dm_state,
+						old_stream, requested_bpc,
+						PIXEL_ENCODING_RGB, is_hdmi_ep);
+		if (!stream)
 			drm_err(adev_to_drm(adev), "Failed to create stream for sink!\n");
-			break;
-		}
+		return stream;
+	}
 
-		dc_result = dc_validate_stream(adev->dm.dc, stream);
+	signal = aconnector->dc_link->connector_signal;
 
-		if (!aconnector) /* writeback connector */
-			return stream;
+	/*
+	 * Determine whether this is a native HDMI sink or a DP->HDMI dongle.
+	 * Since we check for it a few times below, cache the result.
+	 */
+	is_hdmi_ep = (signal == SIGNAL_TYPE_HDMI_TYPE_A ||
+		     signal == SIGNAL_TYPE_HDMI_FRL 	||
+		     aconnector->dc_link->dpcd_caps.dongle_type ==
+			     DISPLAY_DONGLE_DP_HDMI_CONVERTER);
+
+	/*
+	 * Build the set of pixel encodings this sink advertises, so we only
+	 * ever validate combinations the display can actually accept. Ordered
+	 * best-first: RGB / YCbCr444 (full bandwidth) -> YCbCr422 -> YCbCr420.
+	 *
+	 *  - RGB is the mandatory baseline and always available.
+	 *  - YCbCr444 is only meaningful for native HDMI sinks.
+	 *  - A 420-only mode collapses the mask to YCbCr420 alone.
+	 *  - The debugfs force_yuv420_output / force_yuv422_output overrides
+	 *    pin the encoding to a single value when set. An explicit YCbCr420
+	 *    force is honoured even on modes the sink only lists as RGB/4:4:4
+	 *    capable (drm_mode_is_420_also() clear), as required for HDMI
+	 *    compliance testing; dc_validate_stream() still rejects anything
+	 *    the link genuinely cannot carry. The YCbCr422 force stays gated on
+	 *    the sink's advertised caps.
+	 */
+	if (drm_mode_is_420_only(info, drm_mode) ||
+	    aconnector->force_yuv420_output) {
+		encoding_mask = BIT(PIXEL_ENCODING_YCBCR420);
+	} else if (aconnector->force_yuv422_output &&
+		   (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))) {
+		encoding_mask = BIT(PIXEL_ENCODING_YCBCR422);
+	} else {
+		encoding_mask = BIT(PIXEL_ENCODING_RGB);
+
+		if ((info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444)) &&
+		    is_hdmi_ep)
+			encoding_mask |= BIT(PIXEL_ENCODING_YCBCR444);
+
+		if (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
+			encoding_mask |= BIT(PIXEL_ENCODING_YCBCR422);
+
+		if (drm_mode_is_420_also(info, drm_mode))
+			encoding_mask |= BIT(PIXEL_ENCODING_YCBCR420);
+	}
+
+	/*
+	 * Build the set of bit depths to try, high-to-low. Start from the
+	 * atomic-requested cap and clear anything the sink cannot do:
+	 *
+	 *  - Never exceed the requested bpc.
+	 *  - HDMI/FRL and DP->HDMI dongles have no defined 6 bpc mode.
+	 *  - Any depth above the EDID-reported bpc is dropped.
+	 *
+	 * amdgpu_dm_convert_color_depth_from_display_info() applies the final
+	 * per-encoding cap (e.g. YCbCr420 deep-colour limits) when the stream
+	 * is built, so this mask only needs the coarse sink limits.
+	 */
+	for (j = 0; j < ARRAY_SIZE(bpc_order); j++) {
+		u8 bpc = bpc_order[j];
+
+		if (requested_bpc > 0 && bpc > requested_bpc)
+			continue;
+
+		if (bpc == 6 && is_hdmi_ep)
+			continue;
+
+		if (info->bpc && bpc > info->bpc)
+			continue;
+
+		bpc_mask |= BIT(bpc);
+	}
+
+	/*
+	 * Enumerate the supported (encoding, bpc) combinations in priority
+	 * order and return the first that validates. Because the masks only
+	 * contain sink-supported entries, this is generic across connector
+	 * types and needs no encoding-specific fallback afterwards.
+	 *
+	 * The selection lives entirely on the stack and is passed by value to
+	 * create_stream_for_sink(); no shared connector state is mutated. This
+	 * matters because this helper runs concurrently from the connector
+	 * probe worker (->mode_valid) and from a compositor's atomic check on
+	 * the same connector.
+	 */
+	for (i = 0; i < ARRAY_SIZE(encoding_order); i++) {
+		enum dc_pixel_encoding enc = encoding_order[i];
+
+		if (!(encoding_mask & BIT(enc)))
+			continue;
+
+		for (j = 0; j < ARRAY_SIZE(bpc_order); j++) {
+			u8 bpc = bpc_order[j];
 
-		if (dc_result == DC_OK && stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
-			dc_result = dm_dp_mst_is_port_support_mode(aconnector, stream);
+			if (!(bpc_mask & BIT(bpc)))
+				continue;
 
-		if (dc_result == DC_OK)
-			dc_result = dm_validate_stream_and_context(adev->dm.dc, stream);
+			drm_dbg_kms(connector->dev,
+				    "Trying %s with %d bpc (encoding_mask=0x%x bpc_mask=0x%x requested_bpc=%d drm max_bpc)\n",
+				    dc_pixel_encoding_to_str(enc), bpc,
+				    encoding_mask, bpc_mask, requested_bpc);
 
-		if (dc_result != DC_OK) {
-			drm_dbg_kms(connector->dev, "Pruned mode %d x %d (clk %d) %s %s -- %s\n",
+			stream = create_stream_for_sink(connector, drm_mode,
+							dm_state, old_stream,
+							bpc, enc, is_hdmi_ep);
+			if (stream == NULL) {
+				drm_err(adev_to_drm(adev), "Failed to create stream for sink!\n");
+				return NULL;
+			}
+
+			dc_result = dc_validate_stream(adev->dm.dc, stream);
+
+			if (dc_result == DC_OK &&
+			    stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
+				dc_result = dm_dp_mst_is_port_support_mode(aconnector, stream);
+
+			if (dc_result == DC_OK)
+				dc_result = dm_validate_stream_and_context(adev->dm.dc, stream);
+
+			if (dc_result == DC_OK)
+				return stream;
+
+			drm_dbg_kms(connector->dev, "Pruned mode %d x %d (refresh rate %d) %s %s -- %s\n",
 				      drm_mode->hdisplay,
 				      drm_mode->vdisplay,
-				      drm_mode->clock,
+				      drm_mode_vrefresh(drm_mode),
 				      dc_pixel_encoding_to_str(stream->timing.pixel_encoding),
 				      dc_color_depth_to_str(stream->timing.display_color_depth),
 				      dc_status_to_str(dc_result));
 
 			dc_stream_release(stream);
 			stream = NULL;
-			requested_bpc -= 2; /* lower bpc to retry validation */
 		}
+	}
 
-	} while (stream == NULL && requested_bpc >= bpc_limit);
-
-	switch (dc_result) {
 	/*
-	 * If we failed to validate DP bandwidth stream with the requested RGB color depth,
-	 * we try to fallback and configure in order:
-	 * YUV422 (8bpc, 6bpc)
-	 * YUV420 (8bpc, 6bpc)
+	 * Every sink-supported combination was exhausted without validating;
+	 * the mode is genuinely unsupported on this link.
 	 */
-	case DC_FAIL_ENC_VALIDATE:
-	case DC_EXCEED_DONGLE_CAP:
-	case DC_NO_DP_LINK_BANDWIDTH:
-		/* recursively entered twice and already tried both YUV422 and YUV420 */
-		if (aconnector->force_yuv422_output && aconnector->force_yuv420_output)
-			break;
-		/* first failure; try YUV422 */
-		if (!aconnector->force_yuv422_output) {
-			drm_dbg_kms(connector->dev, "%s:%d Validation failed with %d, retrying w/ YUV422\n",
-				    __func__, __LINE__, dc_result);
-			aconnector->force_yuv422_output = true;
-		/* recursively entered and YUV422 failed, try YUV420 */
-		} else if (!aconnector->force_yuv420_output) {
-			drm_dbg_kms(connector->dev, "%s:%d Validation failed with %d, retrying w/ YUV420\n",
-				    __func__, __LINE__, dc_result);
-			aconnector->force_yuv420_output = true;
-		}
-		stream = amdgpu_dm_create_validate_stream_for_sink(connector, drm_mode,
-							 dm_state, old_stream);
-		aconnector->force_yuv422_output = false;
-		aconnector->force_yuv420_output = false;
-		break;
-	case DC_OK:
-		break;
-	default:
-		drm_dbg_kms(connector->dev, "%s:%d Unhandled validation failure %d\n",
-			    __func__, __LINE__, dc_result);
-		break;
-	}
-
-	return stream;
+	return NULL;
 }
 EXPORT_IF_KUNIT(amdgpu_dm_create_validate_stream_for_sink);
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h
index 13c54229d72c..4e9eb3ff2c90 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.h
@@ -189,13 +189,17 @@ void fill_stream_properties_from_drm_display_mode(
 	const struct drm_connector *connector,
 	const struct drm_connector_state *connector_state,
 	const struct dc_stream_state *old_stream,
-	int requested_bpc);
+	int requested_bpc,
+	enum dc_pixel_encoding requested_encoding,
+	bool is_hdmi_ep);
 struct dc_stream_state *
 create_stream_for_sink(struct drm_connector *connector,
 		       const struct drm_display_mode *drm_mode,
 		       const struct dm_connector_state *dm_state,
 		       const struct dc_stream_state *old_stream,
-		       int requested_bpc);
+		       int requested_bpc,
+		       enum dc_pixel_encoding requested_encoding,
+		       bool is_hdmi_ep);
 enum drm_connector_status
 amdgpu_dm_connector_poll(struct amdgpu_dm_connector *aconnector, bool force);
 enum drm_connector_status
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 22/41] drm/amd/display: Unify force_yuv debugfs into force_yuv_pixel_format
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (18 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 21/41] drm/amd/display: Refactor stream validation Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 23/41] drm/amd/display: Align connector KUnit tests with stream validation refactor Roman.Li
                   ` (19 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen

From: Ivan Lipski <ivan.lipski@amd.com>

[Why]
The connector exposed a single force_yuv420_output boolean debugfs and
carried force_yuv420_output / force_yuv422_output boolean fields to force a
chroma encoding. This cannot express "force RGB" or "force YCbCr444", and
diverges from the upstream amdgpu_dm which uses a single
force_yuv_pixel_format field keyed on enum dc_pixel_encoding.

[How]
- Replace the two boolean fields with a single uint8_t
  force_yuv_pixel_format holding an enum dc_pixel_encoding value
  (PIXEL_ENCODING_UNDEFINED == no override).
- Replace the force_yuv420_output boolean debugfs with a read/write
  force_yuv_pixel_format file that takes the encoding directly
  (1=RGB, 2=YCbCr422, 3=YCbCr444, 4=YCbCr420), validated against
  PIXEL_ENCODING_COUNT.
- Convert the existing readers/writers in amdgpu_dm_connector.c to the
  new field, preserving current behaviour.
- Add YCbCr444 force support now that the field can express it.

Assisted-by: Copilot:claude-opus-4.8
Reviewed-by: Jerry Zuo <jerry.zuo@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |  2 -
 .../display/amdgpu_dm/amdgpu_dm_connector.c   | 23 +++++---
 .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 57 +++++++------------
 3 files changed, 34 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 1ddf5bc88a03..3524931451c8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -857,8 +857,6 @@ struct amdgpu_dm_connector {
 	struct mutex hpd_lock;
 
 	bool fake_enable;
-	bool force_yuv420_output;
-	bool force_yuv422_output;
 	uint8_t force_yuv_pixel_format;
 	struct dsc_preferred_settings dsc_settings;
 	struct psr_caps psr_caps;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
index 825c3408763c..4304520d2484 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c
@@ -147,7 +147,7 @@ STATIC_IFN_KUNIT int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
 		int max_bpc = conn_state->max_requested_bpc;
 
 		is_y420 = drm_mode_is_420_also(&connector->display_info, adjusted_mode) &&
-			  aconnector->force_yuv420_output;
+			  aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR420;
 		color_depth = amdgpu_dm_convert_color_depth_from_display_info(connector,
 								    is_y420,
 								    max_bpc);
@@ -2280,20 +2280,25 @@ amdgpu_dm_create_validate_stream_for_sink(struct drm_connector *connector,
 	 *  - RGB is the mandatory baseline and always available.
 	 *  - YCbCr444 is only meaningful for native HDMI sinks.
 	 *  - A 420-only mode collapses the mask to YCbCr420 alone.
-	 *  - The debugfs force_yuv420_output / force_yuv422_output overrides
-	 *    pin the encoding to a single value when set. An explicit YCbCr420
-	 *    force is honoured even on modes the sink only lists as RGB/4:4:4
-	 *    capable (drm_mode_is_420_also() clear), as required for HDMI
-	 *    compliance testing; dc_validate_stream() still rejects anything
-	 *    the link genuinely cannot carry. The YCbCr422 force stays gated on
+	 *  - The debugfs force_yuv_pixel_format override pins the encoding to a
+	 *    single dc_pixel_encoding when set (PIXEL_ENCODING_UNDEFINED means
+	 *    "no override"). An explicit YCbCr420 force is honoured even on
+	 *    modes the sink only lists as RGB/4:4:4 capable
+	 *    (drm_mode_is_420_also() clear), as required for HDMI compliance
+	 *    testing; dc_validate_stream() still rejects anything the link
+	 *    genuinely cannot carry. The YCbCr422/YCbCr444 forces stay gated on
 	 *    the sink's advertised caps.
 	 */
 	if (drm_mode_is_420_only(info, drm_mode) ||
-	    aconnector->force_yuv420_output) {
+	    aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR420) {
 		encoding_mask = BIT(PIXEL_ENCODING_YCBCR420);
-	} else if (aconnector->force_yuv422_output &&
+	} else if (aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR422 &&
 		   (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))) {
 		encoding_mask = BIT(PIXEL_ENCODING_YCBCR422);
+	} else if (aconnector->force_yuv_pixel_format == PIXEL_ENCODING_YCBCR444 &&
+		   (info->color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444)) &&
+		   is_hdmi_ep) {
+		encoding_mask = BIT(PIXEL_ENCODING_YCBCR444);
 	} else {
 		encoding_mask = BIT(PIXEL_ENCODING_RGB);
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
index 830cf8da06b4..c4b2fc690fd7 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
@@ -3199,57 +3199,42 @@ static const struct {
 };
 
 /*
- * Force YUV420 output if available from the given mode
+ * Force a specific pixel encoding for the given connector, overriding the
+ * encoding that stream validation would otherwise pick. The value is an
+ * enum dc_pixel_encoding:
+ *
+ *   0 - PIXEL_ENCODING_UNDEFINED (no override, default)
+ *   1 - PIXEL_ENCODING_RGB
+ *   2 - PIXEL_ENCODING_YCBCR422
+ *   3 - PIXEL_ENCODING_YCBCR444
+ *   4 - PIXEL_ENCODING_YCBCR420
  */
-static int force_yuv420_output_set(void *data, u64 val)
+static int force_yuv_pixel_format_set(void *data, u64 val)
 {
 	struct amdgpu_dm_connector *connector = data;
 
-	connector->force_yuv420_output = (bool)val;
-	connector->force_yuv_pixel_format = PIXEL_ENCODING_YCBCR420;
+	if (val >= PIXEL_ENCODING_COUNT)
+		return -EINVAL;
+
+	connector->force_yuv_pixel_format = (uint8_t)val;
 
 	return 0;
 }
 
 /*
- * Check if YUV420 is forced when available from the given mode
+ * Read back the pixel encoding currently forced on the given connector.
  */
-static int force_yuv420_output_get(void *data, u64 *val)
+static int force_yuv_pixel_format_get(void *data, u64 *val)
 {
 	struct amdgpu_dm_connector *connector = data;
 
-	*val = connector->force_yuv420_output;
+	*val = connector->force_yuv_pixel_format;
 
 	return 0;
 }
 
-DEFINE_DEBUGFS_ATTRIBUTE(force_yuv420_output_fops, force_yuv420_output_get,
-			 force_yuv420_output_set, "%llu\n");
-
-static int force_yuv422_output_set(void *data, u64 val)
-{
-      struct amdgpu_dm_connector *connector = data;
-
-      connector->force_yuv422_output = (bool)val;
-      connector->force_yuv_pixel_format = PIXEL_ENCODING_YCBCR422;
-
-      return 0;
-}
-
-DEFINE_DEBUGFS_ATTRIBUTE(force_yuv422_output_fops, NULL,
-                       force_yuv422_output_set, "%llu\n");
-
-static int force_yuv444_output_set(void *data, u64 val)
-{
-      struct amdgpu_dm_connector *connector = data;
-
-      connector->force_yuv_pixel_format = PIXEL_ENCODING_YCBCR444;
-
-      return 0;
-}
-
-DEFINE_DEBUGFS_ATTRIBUTE(force_yuv444_output_fops, NULL,
-                       force_yuv444_output_set, "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(force_yuv_pixel_format_fops, force_yuv_pixel_format_get,
+			 force_yuv_pixel_format_set, "%llu\n");
 
 /*
  *  Read Replay state
@@ -3699,9 +3684,7 @@ static const struct {
 	char *name;
 	const struct file_operations *fops;
 } connector_debugfs_entries[] = {
-		{"force_yuv420_output", &force_yuv420_output_fops},
-		{"force_yuv422_output", &force_yuv422_output_fops},
-		{"force_yuv444_output", &force_yuv444_output_fops},
+		{"force_yuv_pixel_format", &force_yuv_pixel_format_fops},
 		{"trigger_hotplug", &trigger_hotplug_debugfs_fops},
 		{"internal_display", &internal_display_fops},
 		{"odm_combine_segments", &odm_combine_segments_fops}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 23/41] drm/amd/display: Align connector KUnit tests with stream validation refactor
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (19 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 22/41] drm/amd/display: Unify force_yuv debugfs into force_yuv_pixel_format Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 24/41] drm/amd/display: Increase fclk change latency on dcn351 Roman.Li
                   ` (18 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen

From: Ivan Lipski <ivan.lipski@amd.com>

[Why&How]
Update the amdgpu_dm_connector KUnit tests for the new
fill_stream_properties_from_drm_display_mode() and create_stream_for_sink()
signatures, which now take an explicit pixel encoding and an is_hdmi_ep
flag instead of deriving the encoding from connector state.

- Pass PIXEL_ENCODING_RGB / is_hdmi_ep=false to all existing call sites.
- Add cases verifying the caller-selected encoding is applied verbatim
  (YCbCr420/422/444), replacing the old display-info-derived behaviour.
- Add cases covering the is_hdmi_ep TMDS colour-depth clamp: depth is
  reduced when over the sink limit on an HDMI endpoint and left untouched
  otherwise.

Assisted-by: Copilot:claude-opus-4.8
Reviewed-by: Jerry Zuo <jerry.zuo@amd.com>
Signed-off-by: Ivan Lipski <ivan.lipski@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../tests/amdgpu_dm_connector_test.c          | 155 ++++++++++++++++--
 1 file changed, 141 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
index 1a8f02c78c4d..1658d4d5997a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
@@ -3416,7 +3416,8 @@ static void dm_test_fill_stream_borders_zeroed(struct kunit *test)
 	timing->v_border_bottom = 8;
 
 	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
-		&ctx->aconnector->base, ctx->conn_state, NULL, 8);
+		&ctx->aconnector->base, ctx->conn_state, NULL, 8,
+		PIXEL_ENCODING_RGB, false);
 
 	KUNIT_EXPECT_EQ(test, (int)timing->h_border_left, 0);
 	KUNIT_EXPECT_EQ(test, (int)timing->h_border_right, 0);
@@ -3437,7 +3438,8 @@ static void dm_test_fill_stream_rgb_defaults(struct kunit *test)
 	struct dc_crtc_timing *timing = &ctx->stream->timing;
 
 	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
-		&ctx->aconnector->base, ctx->conn_state, NULL, 8);
+		&ctx->aconnector->base, ctx->conn_state, NULL, 8,
+		PIXEL_ENCODING_RGB, false);
 
 	KUNIT_EXPECT_EQ(test, (int)timing->pixel_encoding, (int)PIXEL_ENCODING_RGB);
 	KUNIT_EXPECT_EQ(test, (int)timing->timing_3d_format,
@@ -3463,7 +3465,8 @@ static void dm_test_fill_stream_sync_polarity_positive(struct kunit *test)
 	ctx->mode->flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;
 
 	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
-		&ctx->aconnector->base, ctx->conn_state, NULL, 8);
+		&ctx->aconnector->base, ctx->conn_state, NULL, 8,
+		PIXEL_ENCODING_RGB, false);
 
 	KUNIT_EXPECT_EQ(test, (int)timing->flags.HSYNC_POSITIVE_POLARITY, 1);
 	KUNIT_EXPECT_EQ(test, (int)timing->flags.VSYNC_POSITIVE_POLARITY, 1);
@@ -3482,7 +3485,8 @@ static void dm_test_fill_stream_sync_polarity_negative(struct kunit *test)
 	ctx->mode->flags = 0;
 
 	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
-		&ctx->aconnector->base, ctx->conn_state, NULL, 8);
+		&ctx->aconnector->base, ctx->conn_state, NULL, 8,
+		PIXEL_ENCODING_RGB, false);
 
 	KUNIT_EXPECT_EQ(test, (int)timing->flags.HSYNC_POSITIVE_POLARITY, 0);
 	KUNIT_EXPECT_EQ(test, (int)timing->flags.VSYNC_POSITIVE_POLARITY, 0);
@@ -3511,7 +3515,8 @@ static void dm_test_fill_stream_inherits_old_stream(struct kunit *test)
 	ctx->mode->flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC;
 
 	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
-		&ctx->aconnector->base, ctx->conn_state, old_stream, 8);
+		&ctx->aconnector->base, ctx->conn_state, old_stream, 8,
+		PIXEL_ENCODING_RGB, false);
 
 	KUNIT_EXPECT_EQ(test, (int)timing->vic, 16);
 	KUNIT_EXPECT_EQ(test, (int)timing->flags.HSYNC_POSITIVE_POLARITY, 1);
@@ -3541,7 +3546,8 @@ static void dm_test_fill_stream_timing_from_crtc(struct kunit *test)
 	ctx->mode->crtc_clock = 148500;
 
 	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
-		&ctx->aconnector->base, ctx->conn_state, NULL, 8);
+		&ctx->aconnector->base, ctx->conn_state, NULL, 8,
+		PIXEL_ENCODING_RGB, false);
 
 	KUNIT_EXPECT_EQ(test, (int)timing->h_addressable, 1920);
 	KUNIT_EXPECT_EQ(test, (int)timing->h_total, 2200);
@@ -3568,7 +3574,8 @@ static void dm_test_fill_stream_color_depth_requested_bpc(struct kunit *test)
 	ctx->aconnector->base.display_info.bpc = 12;
 
 	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
-		&ctx->aconnector->base, ctx->conn_state, NULL, 10);
+		&ctx->aconnector->base, ctx->conn_state, NULL, 10,
+		PIXEL_ENCODING_RGB, false);
 
 	KUNIT_EXPECT_EQ(test, (int)timing->display_color_depth,
 			(int)COLOR_DEPTH_101010);
@@ -3585,7 +3592,8 @@ static void dm_test_fill_stream_content_type(struct kunit *test)
 	ctx->conn_state->content_type = DRM_MODE_CONTENT_TYPE_GRAPHICS;
 
 	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
-		&ctx->aconnector->base, ctx->conn_state, NULL, 8);
+		&ctx->aconnector->base, ctx->conn_state, NULL, 8,
+		PIXEL_ENCODING_RGB, false);
 
 	KUNIT_EXPECT_EQ(test, (int)ctx->stream->content_type,
 			(int)DISPLAY_CONTENT_TYPE_GRAPHICS);
@@ -3603,12 +3611,121 @@ static void dm_test_fill_stream_aspect_ratio(struct kunit *test)
 	ctx->mode->picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9;
 
 	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
-		&ctx->aconnector->base, ctx->conn_state, NULL, 8);
+		&ctx->aconnector->base, ctx->conn_state, NULL, 8,
+		PIXEL_ENCODING_RGB, false);
 
 	KUNIT_EXPECT_EQ(test, (int)timing->aspect_ratio,
 			(int)ASPECT_RATIO_16_9);
 }
 
+/**
+ * dm_test_fill_stream_encoding_from_caller_ycbcr420 - Test caller-selected 420
+ * @test: The KUnit test context
+ *
+ * The helper no longer derives the pixel encoding from the display info; it
+ * applies whatever the caller selected. Passing YCbCr420 must be honoured even
+ * though the DisplayPort sink advertises no YCbCr color formats.
+ */
+static void dm_test_fill_stream_encoding_from_caller_ycbcr420(struct kunit *test)
+{
+	struct dm_test_fill_ctx *ctx = dm_test_fill_ctx_alloc(test);
+	struct dc_crtc_timing *timing = &ctx->stream->timing;
+
+	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
+		&ctx->aconnector->base, ctx->conn_state, NULL, 8,
+		PIXEL_ENCODING_YCBCR420, false);
+
+	KUNIT_EXPECT_EQ(test, (int)timing->pixel_encoding,
+			(int)PIXEL_ENCODING_YCBCR420);
+}
+
+/**
+ * dm_test_fill_stream_encoding_from_caller_ycbcr422 - Test caller-selected 422
+ * @test: The KUnit test context
+ *
+ * A caller-selected YCbCr422 encoding is applied verbatim.
+ */
+static void dm_test_fill_stream_encoding_from_caller_ycbcr422(struct kunit *test)
+{
+	struct dm_test_fill_ctx *ctx = dm_test_fill_ctx_alloc(test);
+	struct dc_crtc_timing *timing = &ctx->stream->timing;
+
+	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
+		&ctx->aconnector->base, ctx->conn_state, NULL, 8,
+		PIXEL_ENCODING_YCBCR422, false);
+
+	KUNIT_EXPECT_EQ(test, (int)timing->pixel_encoding,
+			(int)PIXEL_ENCODING_YCBCR422);
+}
+
+/**
+ * dm_test_fill_stream_encoding_from_caller_ycbcr444 - Test caller-selected 444
+ * @test: The KUnit test context
+ *
+ * A caller-selected YCbCr444 encoding is applied verbatim.
+ */
+static void dm_test_fill_stream_encoding_from_caller_ycbcr444(struct kunit *test)
+{
+	struct dm_test_fill_ctx *ctx = dm_test_fill_ctx_alloc(test);
+	struct dc_crtc_timing *timing = &ctx->stream->timing;
+
+	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
+		&ctx->aconnector->base, ctx->conn_state, NULL, 8,
+		PIXEL_ENCODING_YCBCR444, false);
+
+	KUNIT_EXPECT_EQ(test, (int)timing->pixel_encoding,
+			(int)PIXEL_ENCODING_YCBCR444);
+}
+
+/**
+ * dm_test_fill_stream_hdmi_ep_clamps_depth - Test HDMI TMDS depth clamp applied
+ * @test: The KUnit test context
+ *
+ * With is_hdmi_ep set the colour depth is clamped to what the sink's max TMDS
+ * clock allows: a 10bpc request that exceeds the limit is reduced to 8bpc.
+ */
+static void dm_test_fill_stream_hdmi_ep_clamps_depth(struct kunit *test)
+{
+	struct dm_test_fill_ctx *ctx = dm_test_fill_ctx_alloc(test);
+	struct dc_crtc_timing *timing = &ctx->stream->timing;
+
+	ctx->aconnector->base.display_info.bpc = 10;
+	/* 10bpc RGB needs 185625 KHz, over the sink's 160 MHz TMDS limit. */
+	ctx->aconnector->base.display_info.max_tmds_clock = 160000;
+	ctx->mode->crtc_clock = 148500;
+
+	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
+		&ctx->aconnector->base, ctx->conn_state, NULL, 10,
+		PIXEL_ENCODING_RGB, true);
+
+	KUNIT_EXPECT_EQ(test, (int)timing->display_color_depth,
+			(int)COLOR_DEPTH_888);
+}
+
+/**
+ * dm_test_fill_stream_non_hdmi_ep_keeps_depth - Test no TMDS clamp off HDMI
+ * @test: The KUnit test context
+ *
+ * With is_hdmi_ep clear the TMDS clamp is skipped, so the same over-limit
+ * 10bpc request is left untouched. The clamp is HDMI-specific.
+ */
+static void dm_test_fill_stream_non_hdmi_ep_keeps_depth(struct kunit *test)
+{
+	struct dm_test_fill_ctx *ctx = dm_test_fill_ctx_alloc(test);
+	struct dc_crtc_timing *timing = &ctx->stream->timing;
+
+	ctx->aconnector->base.display_info.bpc = 10;
+	ctx->aconnector->base.display_info.max_tmds_clock = 160000;
+	ctx->mode->crtc_clock = 148500;
+
+	fill_stream_properties_from_drm_display_mode(ctx->stream, ctx->mode,
+		&ctx->aconnector->base, ctx->conn_state, NULL, 10,
+		PIXEL_ENCODING_RGB, false);
+
+	KUNIT_EXPECT_EQ(test, (int)timing->display_color_depth,
+			(int)COLOR_DEPTH_101010);
+}
+
 /* Tests for create_stream_for_sink() */
 
 /*
@@ -3687,7 +3804,8 @@ static void dm_test_create_stream_fake_sink_success(struct kunit *test)
 	struct dc_stream_state *stream;
 
 	stream = create_stream_for_sink(&ctx->aconnector->base, ctx->mode,
-					ctx->dm_state, NULL, 8);
+					ctx->dm_state, NULL, 8,
+					PIXEL_ENCODING_RGB, false);
 
 	KUNIT_ASSERT_NOT_NULL(test, stream);
 	dc_stream_release(stream);
@@ -3703,7 +3821,8 @@ static void dm_test_create_stream_sets_dm_context(struct kunit *test)
 	struct dc_stream_state *stream;
 
 	stream = create_stream_for_sink(&ctx->aconnector->base, ctx->mode,
-					ctx->dm_state, NULL, 8);
+					ctx->dm_state, NULL, 8,
+					PIXEL_ENCODING_RGB, false);
 
 	KUNIT_ASSERT_NOT_NULL(test, stream);
 	KUNIT_EXPECT_PTR_EQ(test, stream->dm_stream_context, ctx->aconnector);
@@ -3720,7 +3839,8 @@ static void dm_test_create_stream_virtual_signal(struct kunit *test)
 	struct dc_stream_state *stream;
 
 	stream = create_stream_for_sink(&ctx->aconnector->base, ctx->mode,
-					ctx->dm_state, NULL, 8);
+					ctx->dm_state, NULL, 8,
+					PIXEL_ENCODING_RGB, false);
 
 	KUNIT_ASSERT_NOT_NULL(test, stream);
 	KUNIT_EXPECT_EQ(test, (int)stream->signal, (int)SIGNAL_TYPE_VIRTUAL);
@@ -3739,7 +3859,8 @@ static void dm_test_create_stream_scaling_src(struct kunit *test)
 	struct dc_stream_state *stream;
 
 	stream = create_stream_for_sink(&ctx->aconnector->base, ctx->mode,
-					ctx->dm_state, NULL, 8);
+					ctx->dm_state, NULL, 8,
+					PIXEL_ENCODING_RGB, false);
 
 	KUNIT_ASSERT_NOT_NULL(test, stream);
 	KUNIT_EXPECT_EQ(test, (int)stream->src.width, 1920);
@@ -3770,7 +3891,8 @@ static void dm_test_create_stream_existing_sink(struct kunit *test)
 	ctx->aconnector->dc_sink = sink;
 
 	stream = create_stream_for_sink(&ctx->aconnector->base, ctx->mode,
-					ctx->dm_state, NULL, 8);
+					ctx->dm_state, NULL, 8,
+					PIXEL_ENCODING_RGB, false);
 
 	KUNIT_ASSERT_NOT_NULL(test, stream);
 	KUNIT_EXPECT_PTR_EQ(test, stream->sink, sink);
@@ -5456,6 +5578,11 @@ static struct kunit_case amdgpu_dm_connector_tests[] = {
 	KUNIT_CASE(dm_test_fill_stream_color_depth_requested_bpc),
 	KUNIT_CASE(dm_test_fill_stream_content_type),
 	KUNIT_CASE(dm_test_fill_stream_aspect_ratio),
+	KUNIT_CASE(dm_test_fill_stream_encoding_from_caller_ycbcr420),
+	KUNIT_CASE(dm_test_fill_stream_encoding_from_caller_ycbcr422),
+	KUNIT_CASE(dm_test_fill_stream_encoding_from_caller_ycbcr444),
+	KUNIT_CASE(dm_test_fill_stream_hdmi_ep_clamps_depth),
+	KUNIT_CASE(dm_test_fill_stream_non_hdmi_ep_keeps_depth),
 	/* create_stream_for_sink */
 	KUNIT_CASE(dm_test_create_stream_fake_sink_success),
 	KUNIT_CASE(dm_test_create_stream_sets_dm_context),
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 24/41] drm/amd/display: Increase fclk change latency on dcn351
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (20 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 23/41] drm/amd/display: Align connector KUnit tests with stream validation refactor Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 25/41] drm/amd/display: Add KUnit tests for crtc set_vblank Roman.Li
                   ` (17 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Sung-huai Wang, Dillon Varone

From: Sung-huai Wang <Danny.Wang@amd.com>

[Why]
fclk change latency is longer than expected on dcn351.

[How]
Increate fclk change latency from 24us to 32us.

Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Sung-huai Wang <Danny.Wang@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c
index 6552b26de845..0c5a2667d526 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c
@@ -206,7 +206,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_51_soc = {
 	.sr_enter_plus_exit_time_us = 30.0,
 	.sr_exit_z8_time_us = 263.0,
 	.sr_enter_plus_exit_z8_time_us = 363.0,
-	.fclk_change_latency_us = 24.0,
+	.fclk_change_latency_us = 39.0,
 	.usr_retraining_latency_us = 2,
 	.writeback_latency_us = 12.0,
 
@@ -215,7 +215,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_51_soc = {
 	.urgent_latency_pixel_data_only_us = 4.0,
 	.urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
 	.urgent_latency_vm_data_only_us = 4.0,
-	.dram_clock_change_latency_us = 34,
+	.dram_clock_change_latency_us = 39,
 	.urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
 	.urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
 	.urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 25/41] drm/amd/display: Add KUnit tests for crtc set_vblank
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (21 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 24/41] drm/amd/display: Increase fclk change latency on dcn351 Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 26/41] drm/amd/display: Cover crtc set_vblank workqueue branch Roman.Li
                   ` (16 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha

From: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>

Add coverage for the amdgpu_dm_crtc_set_vblank() paths reached through
amdgpu_dm_crtc_enable_vblank() and amdgpu_dm_crtc_disable_vblank():

- dm_test_crtc_enable_vblank_full_path: VRR-active enable that walks the
  vupdate-irq branch and acquires the crtc/pageflip IRQ references.
- dm_test_crtc_enable_vblank_vupdate_busy: vupdate IRQ rejection aborts
  the enable with -EBUSY.
- dm_test_crtc_enable_vblank_crtc_irq_error: crtc IRQ acquire failure
  aborts the enable with -ENOENT.
- dm_test_crtc_enable_vblank_in_reset: an in-progress GPU reset returns
  early before the vblank workqueue branch.
- dm_test_crtc_disable_vblank_vrr: the VRR disable path turns the vupdate
  IRQ off and releases both IRQ references.

Add shared IRQ-source stubs and setup helpers so amdgpu_irq_get()/put()
succeed without hardware access.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 283 ++++++++++++++++++
 1 file changed, 283 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index fa4986153eda..753150943fba 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -477,6 +477,19 @@ static struct irq_source_info_funcs dm_test_vupdate_irq_src_funcs = {
 	.ack = dm_test_vupdate_irq_src_ack,
 };
 
+/* A .set that fails so dc_interrupt_set() reports the source as busy. */
+static bool dm_test_vupdate_irq_src_set_busy(struct irq_service *irq_service,
+					     const struct irq_source_info *info,
+					     bool enable)
+{
+	return false;
+}
+
+static struct irq_source_info_funcs dm_test_vupdate_irq_src_busy_funcs = {
+	.set = dm_test_vupdate_irq_src_set_busy,
+	.ack = dm_test_vupdate_irq_src_ack,
+};
+
 /**
  * dm_test_crtc_set_vupdate_irq_enable - Test vupdate irq enable/disable success
  * @test: The KUnit test context
@@ -832,6 +845,224 @@ static void dm_test_crtc_enable_vblank_rejects_unconfigured(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), -EINVAL);
 }
 
+/* Stub IRQ source .set so amdgpu_irq_get()/put() pass their funcs->set check. */
+static int dm_test_crtc_irq_src_set(struct amdgpu_device *adev,
+				    struct amdgpu_irq_src *source,
+				    unsigned int type,
+				    enum amdgpu_interrupt_state state)
+{
+	return 0;
+}
+
+static const struct amdgpu_irq_src_funcs dm_test_crtc_irq_src_funcs = {
+	.set = dm_test_crtc_irq_src_set,
+};
+
+/*
+ * dm_test_crtc_arm_irq_src - Prime an IRQ source so get()/put() short-circuit.
+ * @test: The KUnit test context
+ * @src: The amdgpu IRQ source to arm
+ * @count: Initial per-type reference count
+ *
+ * Seeds enabled_types[AMDGPU_CRTC_IRQ_VBLANK1] with @count and installs a
+ * non-NULL funcs->set so amdgpu_irq_get()/amdgpu_irq_put() adjust the refcount
+ * without ever reaching amdgpu_irq_update() (which would touch hardware).
+ */
+static void dm_test_crtc_arm_irq_src(struct kunit *test,
+				     struct amdgpu_irq_src *src, int count)
+{
+	atomic_t *enabled;
+
+	enabled = kunit_kzalloc(test, sizeof(*enabled), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, enabled);
+
+	atomic_set(enabled, count);
+	src->num_types = 1;
+	src->enabled_types = enabled;
+	src->funcs = &dm_test_crtc_irq_src_funcs;
+}
+
+/*
+ * dm_test_crtc_setup_enable - Build an adev/CRTC primed for the vblank enable path.
+ * @test: The KUnit test context
+ * @adev_out: Receives the allocated device
+ * @dce_version: DCE version stamped on the DC (controls dc_supports_vrr())
+ *
+ * Returns a CRTC whose enable path can run to completion: a configured
+ * (enabled) CRTC with crtc_id 0, an initialized single-pipe vblank array, a DC
+ * with @dce_version, a non-reset reset_domain and a dm_crtc_state carrying a
+ * stream+link. IPS support stays disabled so drm_crtc_vblank_restore() is
+ * skipped, and the IRQ subsystem is left uninstalled for callers to arm.
+ */
+static struct amdgpu_crtc *
+dm_test_crtc_setup_enable(struct kunit *test, struct amdgpu_device **adev_out,
+			  enum dce_version dce_version)
+{
+	struct amdgpu_reset_domain *reset_domain;
+	struct dc_stream_state *stream;
+	struct dm_crtc_state *dm_state;
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+	struct dc_link *link;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	KUNIT_ASSERT_EQ(test, drm_vblank_init(&adev->ddev, 1), 0);
+
+	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
+	adev->dm.dc->ctx->dce_version = dce_version;
+
+	/* crtc_id 0 maps to a valid IRQ type only when a CRTC is registered. */
+	adev->mode_info.num_crtc = 1;
+
+	reset_domain = kunit_kzalloc(test, sizeof(*reset_domain), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reset_domain);
+	adev->reset_domain = reset_domain;
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
+	acrtc->base.dev = &adev->ddev;
+	acrtc->base.enabled = true;
+	acrtc->crtc_id = 0;
+
+	link = dm_kunit_alloc_link(test);
+	stream = dm_kunit_alloc_stream(test, link);
+
+	dm_state = kunit_kzalloc(test, sizeof(*dm_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
+	dm_state->stream = stream;
+	acrtc->base.state = &dm_state->base;
+
+	*adev_out = adev;
+	return acrtc;
+}
+
+/**
+ * dm_test_crtc_enable_vblank_full_path - Test the enable path runs to completion
+ * @test: The KUnit test context
+ *
+ * With a configured CRTC on a VRR-capable DC and both crtc/pageflip IRQ sources
+ * armed, the enable path walks the vupdate-irq branch (VRR active, OTG
+ * unassigned so it returns early), acquires both IRQ references and completes
+ * with no vblank workqueue queued.
+ */
+static void dm_test_crtc_enable_vblank_full_path(struct kunit *test)
+{
+	struct dm_crtc_state *acrtc_state;
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+
+	/* DCE_VERSION_8_0 supports VRR -> the vupdate-irq branch is walked. */
+	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_8_0);
+
+	/* OTG unassigned -> amdgpu_dm_crtc_set_vupdate_irq() returns 0 early. */
+	acrtc->otg_inst = -1;
+	/* VRR active so the enable path takes the vupdate-irq branch. */
+	acrtc_state = to_dm_crtc_state(acrtc->base.state);
+	acrtc_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
+
+	adev->irq.installed = true;
+	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 1);
+	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 1);
+
+	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), 0);
+}
+
+/**
+ * dm_test_crtc_enable_vblank_vupdate_busy - Test vupdate failure aborts enable
+ * @test: The KUnit test context
+ *
+ * When VRR is active and the DC rejects the vupdate IRQ request, the enable
+ * path must propagate the error (-EBUSY) before touching the crtc/pageflip
+ * IRQs.
+ */
+static void dm_test_crtc_enable_vblank_vupdate_busy(struct kunit *test)
+{
+	struct irq_source_info *info;
+	struct resource_pool *res_pool;
+	struct dm_crtc_state *acrtc_state;
+	struct irq_service *irqs;
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+	int i;
+
+	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_8_0);
+
+	/* OTG assigned and VRR active so set_vupdate_irq() calls into DC. */
+	acrtc->otg_inst = 0;
+	acrtc_state = to_dm_crtc_state(acrtc->base.state);
+	acrtc_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
+
+	res_pool = kunit_kzalloc(test, sizeof(*res_pool), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res_pool);
+	irqs = kunit_kzalloc(test, sizeof(*irqs), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, irqs);
+
+	/* Per-source .set fails so dc_interrupt_set() reports the source busy. */
+	info = kunit_kzalloc(test, sizeof(*info) * DAL_IRQ_SOURCES_NUMBER,
+			     GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, info);
+	for (i = 0; i < DAL_IRQ_SOURCES_NUMBER; i++)
+		info[i].funcs = &dm_test_vupdate_irq_src_busy_funcs;
+
+	irqs->info = info;
+	res_pool->irqs = irqs;
+	adev->dm.dc->res_pool = res_pool;
+
+	KUNIT_EXPECT_EQ(test,
+			amdgpu_dm_crtc_enable_vblank(&acrtc->base), -EBUSY);
+}
+
+/**
+ * dm_test_crtc_enable_vblank_crtc_irq_error - Test crtc IRQ failure aborts enable
+ * @test: The KUnit test context
+ *
+ * On a non-VRR DC the vupdate-irq branch is skipped. With the IRQ subsystem
+ * uninstalled, amdgpu_irq_get() on the crtc IRQ returns -ENOENT and the enable
+ * path must propagate it before touching the pageflip IRQ.
+ */
+static void dm_test_crtc_enable_vblank_crtc_irq_error(struct kunit *test)
+{
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+
+	/* DCE_VERSION_6_0 has no VRR, so the vupdate-irq branch is skipped. */
+	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_6_0);
+
+	/* IRQ subsystem not installed -> amdgpu_irq_get() returns -ENOENT. */
+	adev->irq.installed = false;
+
+	KUNIT_EXPECT_EQ(test,
+			amdgpu_dm_crtc_enable_vblank(&acrtc->base), -ENOENT);
+}
+
+/**
+ * dm_test_crtc_enable_vblank_in_reset - Test enable returns early during GPU reset
+ * @test: The KUnit test context
+ *
+ * After acquiring the IRQ references, an in-progress GPU reset must short the
+ * enable path so it returns 0 without queuing any vblank control work.
+ */
+static void dm_test_crtc_enable_vblank_in_reset(struct kunit *test)
+{
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+
+	/* DCE_VERSION_6_0 has no VRR, so the vupdate-irq branch is skipped. */
+	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_6_0);
+
+	adev->irq.installed = true;
+	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 1);
+	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 1);
+
+	/* Mid-reset: return 0 before the vblank workqueue branch is reached. */
+	atomic_set(&adev->reset_domain->in_gpu_reset, 1);
+
+	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), 0);
+}
+
 /* Tests for amdgpu_dm_crtc_update_crtc_active_planes() */
 
 /**
@@ -1307,6 +1538,53 @@ static void dm_test_crtc_disable_vblank_no_irq_installed(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, adev->dm.active_vblank_irq_count, 0);
 }
 
+/**
+ * dm_test_crtc_disable_vblank_vrr - Test disable path releases IRQs on a VRR DC
+ * @test: The KUnit test context
+ *
+ * On a VRR-capable DC the disable path turns the vupdate IRQ off (OTG
+ * unassigned so it returns early), releases the armed crtc and pageflip IRQ
+ * references and completes without queuing vblank control work.
+ */
+static void dm_test_crtc_disable_vblank_vrr(struct kunit *test)
+{
+	struct amdgpu_reset_domain *reset_domain;
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
+	/* DCE_VERSION_8_0 supports VRR -> the vupdate-irq branch is walked. */
+	adev->dm.dc->ctx->dce_version = DCE_VERSION_8_0;
+
+	adev->mode_info.num_crtc = 1;
+	adev->irq.installed = true;
+
+	reset_domain = kunit_kzalloc(test, sizeof(*reset_domain), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reset_domain);
+	adev->reset_domain = reset_domain;
+
+	/* Seed with 2 so amdgpu_irq_put() drops to a non-zero refcount. */
+	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 2);
+	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 2);
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
+	acrtc->base.dev = &adev->ddev;
+	acrtc->crtc_id = 0;
+	/* OTG unassigned -> amdgpu_dm_crtc_set_vupdate_irq() returns 0 early. */
+	acrtc->otg_inst = -1;
+
+	amdgpu_dm_crtc_disable_vblank(&acrtc->base);
+
+	/* Both IRQ references were released without underflow. */
+	KUNIT_EXPECT_EQ(test, atomic_read(&adev->crtc_irq.enabled_types[0]), 1);
+	KUNIT_EXPECT_EQ(test, atomic_read(&adev->pageflip_irq.enabled_types[0]), 1);
+}
+
 static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	/* amdgpu_dm_crtc_modeset_required */
 	KUNIT_CASE(dm_test_crtc_modeset_required_active_mode_changed),
@@ -1352,6 +1630,10 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_crtc_set_static_screen_optimze_psr_su_skips),
 	/* amdgpu_dm_crtc_enable_vblank */
 	KUNIT_CASE(dm_test_crtc_enable_vblank_rejects_unconfigured),
+	KUNIT_CASE(dm_test_crtc_enable_vblank_full_path),
+	KUNIT_CASE(dm_test_crtc_enable_vblank_vupdate_busy),
+	KUNIT_CASE(dm_test_crtc_enable_vblank_crtc_irq_error),
+	KUNIT_CASE(dm_test_crtc_enable_vblank_in_reset),
 	/* amdgpu_dm_crtc_update_crtc_active_planes */
 	KUNIT_CASE(dm_test_crtc_update_active_planes_no_stream),
 	/* amdgpu_dm_crtc_count_crtc_active_planes */
@@ -1373,6 +1655,7 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_vblank_control_worker_disable_clamps_zero),
 	/* amdgpu_dm_crtc_disable_vblank */
 	KUNIT_CASE(dm_test_crtc_disable_vblank_no_irq_installed),
+	KUNIT_CASE(dm_test_crtc_disable_vblank_vrr),
 	{}
 };
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 26/41] drm/amd/display: Cover crtc set_vblank workqueue branch
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (22 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 25/41] drm/amd/display: Add KUnit tests for crtc set_vblank Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 27/41] drm/amd/display: Cover crtc vblank IPS self-refresh restore Roman.Li
                   ` (15 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha

From: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>

Add dm_test_crtc_enable_vblank_queues_work and
dm_test_crtc_disable_vblank_queues_work to cover the
vblank_control_workqueue branch of amdgpu_dm_crtc_set_vblank():

- The enable test installs a real workqueue, retains the stream and
  queues the control worker, then drains it and checks the active vblank
  IRQ count was incremented.
- The disable test drives the no-stream sub-branch (the stream-retain is
  skipped) and checks the worker decremented the count.

Both seed the ISM so the queued worker takes no state-machine transition,
keeping coverage on the vblank accounting; the ISM state machine itself
is covered by the ISM tests.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 115 ++++++++++++++++++
 1 file changed, 115 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index 753150943fba..74d72289dff6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -1063,6 +1063,50 @@ static void dm_test_crtc_enable_vblank_in_reset(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), 0);
 }
 
+/**
+ * dm_test_crtc_enable_vblank_queues_work - Test enable queues vblank control work
+ * @test: The KUnit test context
+ *
+ * With a vblank control workqueue installed, the enable path allocates a work
+ * item, retains the stream and queues the control worker. Draining the queue
+ * runs the worker, which bumps the active vblank IRQ count. The initial ISM
+ * state has no EXIT_IDLE_REQUESTED transition, so the worker only exercises the
+ * vblank accounting (the ISM state machine is covered by its own tests).
+ */
+static void dm_test_crtc_enable_vblank_queues_work(struct kunit *test)
+{
+	struct dm_crtc_state *acrtc_state;
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+
+	/* DCE_VERSION_8_0 supports VRR -> the vupdate-irq branch is walked. */
+	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_8_0);
+
+	/* OTG unassigned -> amdgpu_dm_crtc_set_vupdate_irq() returns 0 early. */
+	acrtc->otg_inst = -1;
+	acrtc_state = to_dm_crtc_state(acrtc->base.state);
+	acrtc_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
+
+	adev->irq.installed = true;
+	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 1);
+	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 1);
+
+	/* Real workqueue so the queue_work() branch runs the control worker. */
+	mutex_init(&adev->dm.dc_lock);
+	adev->dm.vblank_control_workqueue =
+		create_singlethread_workqueue("dm_test_vblank");
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.vblank_control_workqueue);
+
+	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), 0);
+
+	/* Drain the queued worker before the fixture is torn down, then tidy up. */
+	destroy_workqueue(adev->dm.vblank_control_workqueue);
+	adev->dm.vblank_control_workqueue = NULL;
+
+	/* The queued worker ran and accounted the active vblank IRQ. */
+	KUNIT_EXPECT_EQ(test, adev->dm.active_vblank_irq_count, 1);
+}
+
 /* Tests for amdgpu_dm_crtc_update_crtc_active_planes() */
 
 /**
@@ -1585,6 +1629,75 @@ static void dm_test_crtc_disable_vblank_vrr(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, atomic_read(&adev->pageflip_irq.enabled_types[0]), 1);
 }
 
+/**
+ * dm_test_crtc_disable_vblank_queues_work - Test disable queues work without a stream
+ * @test: The KUnit test context
+ *
+ * With a vblank control workqueue installed and a CRTC state carrying no
+ * stream, the disable path queues the control worker without retaining a
+ * stream. Draining the queue runs the worker, which drops the active vblank IRQ
+ * count. The ISM is seeded in a state with no ENTER_IDLE_REQUESTED transition
+ * so the worker only exercises the vblank accounting.
+ */
+static void dm_test_crtc_disable_vblank_queues_work(struct kunit *test)
+{
+	struct amdgpu_reset_domain *reset_domain;
+	struct dm_crtc_state *dm_state;
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+
+	adev = dm_kunit_alloc_adev(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
+
+	adev->dm.dc = dm_kunit_alloc_dc_with_ctx(test);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.dc);
+	/* DCE_VERSION_6_0 has no VRR, so the vupdate-irq branch is skipped. */
+	adev->dm.dc->ctx->dce_version = DCE_VERSION_6_0;
+	adev->dm.active_vblank_irq_count = 2;
+
+	adev->mode_info.num_crtc = 1;
+	adev->irq.installed = true;
+
+	reset_domain = kunit_kzalloc(test, sizeof(*reset_domain), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, reset_domain);
+	adev->reset_domain = reset_domain;
+
+	/* Seed with 2 so amdgpu_irq_put() drops to a non-zero refcount. */
+	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 2);
+	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 2);
+
+	acrtc = kunit_kzalloc(test, sizeof(*acrtc), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, acrtc);
+	acrtc->base.dev = &adev->ddev;
+	acrtc->crtc_id = 0;
+	acrtc->otg_inst = -1;
+	/*
+	 * Seed the ISM in a state where ENTER_IDLE_REQUESTED does not transition
+	 * so the worker skips the ISM power-state dispatch and its timers.
+	 */
+	acrtc->ism.current_state = DM_ISM_STATE_HYSTERESIS_WAITING;
+
+	/* CRTC state with no stream -> the stream-retain branch is skipped. */
+	dm_state = kunit_kzalloc(test, sizeof(*dm_state), GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
+	acrtc->base.state = &dm_state->base;
+
+	/* Real workqueue so the queue_work() branch runs the control worker. */
+	mutex_init(&adev->dm.dc_lock);
+	adev->dm.vblank_control_workqueue =
+		create_singlethread_workqueue("dm_test_vblank");
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev->dm.vblank_control_workqueue);
+
+	amdgpu_dm_crtc_disable_vblank(&acrtc->base);
+
+	/* Drain the queued worker before the fixture is torn down, then tidy up. */
+	destroy_workqueue(adev->dm.vblank_control_workqueue);
+	adev->dm.vblank_control_workqueue = NULL;
+
+	/* The queued worker ran and decremented the active vblank IRQ count. */
+	KUNIT_EXPECT_EQ(test, adev->dm.active_vblank_irq_count, 1);
+}
+
 static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	/* amdgpu_dm_crtc_modeset_required */
 	KUNIT_CASE(dm_test_crtc_modeset_required_active_mode_changed),
@@ -1634,6 +1747,7 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_crtc_enable_vblank_vupdate_busy),
 	KUNIT_CASE(dm_test_crtc_enable_vblank_crtc_irq_error),
 	KUNIT_CASE(dm_test_crtc_enable_vblank_in_reset),
+	KUNIT_CASE(dm_test_crtc_enable_vblank_queues_work),
 	/* amdgpu_dm_crtc_update_crtc_active_planes */
 	KUNIT_CASE(dm_test_crtc_update_active_planes_no_stream),
 	/* amdgpu_dm_crtc_count_crtc_active_planes */
@@ -1656,6 +1770,7 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	/* amdgpu_dm_crtc_disable_vblank */
 	KUNIT_CASE(dm_test_crtc_disable_vblank_no_irq_installed),
 	KUNIT_CASE(dm_test_crtc_disable_vblank_vrr),
+	KUNIT_CASE(dm_test_crtc_disable_vblank_queues_work),
 	{}
 };
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 27/41] drm/amd/display: Cover crtc vblank IPS self-refresh restore
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (23 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 26/41] drm/amd/display: Cover crtc set_vblank workqueue branch Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 28/41] drm/amd/display: Cover crtc vblank restore replay-supported path Roman.Li
                   ` (14 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha

From: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>

Add dm_test_crtc_enable_vblank_ips_restore to cover the IPS/self-refresh
branch of amdgpu_dm_crtc_set_vblank() that calls drm_crtc_vblank_restore().

The test primes the DC with ips_support set and IPS not fully disabled, a
supported PSR version (self-refresh supported) and an immediate-disable
vblank config, so all four conditions gating the restore hold. A stub
get_vblank_timestamp hook is installed on the CRTC so the restore helper
passes its sanity check, and the enable path then runs to completion.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 66 +++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index 74d72289dff6..b64660064902 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -858,6 +858,24 @@ static const struct amdgpu_irq_src_funcs dm_test_crtc_irq_src_funcs = {
 	.set = dm_test_crtc_irq_src_set,
 };
 
+/*
+ * Stub get_vblank_timestamp so drm_crtc_vblank_restore() finds a non-NULL hook.
+ * The CRTC is not registered on the device, so drm_crtc_from_index() returns
+ * NULL and this callback is never actually invoked; it only satisfies the
+ * WARN_ON_ONCE(!crtc->funcs->get_vblank_timestamp) sanity check.
+ */
+static bool dm_test_crtc_get_vblank_timestamp(struct drm_crtc *crtc,
+					      int *max_error,
+					      ktime_t *vblank_time,
+					      bool in_vblank_irq)
+{
+	return false;
+}
+
+static const struct drm_crtc_funcs dm_test_crtc_funcs = {
+	.get_vblank_timestamp = dm_test_crtc_get_vblank_timestamp,
+};
+
 /*
  * dm_test_crtc_arm_irq_src - Prime an IRQ source so get()/put() short-circuit.
  * @test: The KUnit test context
@@ -1107,6 +1125,53 @@ static void dm_test_crtc_enable_vblank_queues_work(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, adev->dm.active_vblank_irq_count, 1);
 }
 
+/**
+ * dm_test_crtc_enable_vblank_ips_restore - Test IPS/self-refresh vblank restore
+ * @test: The KUnit test context
+ *
+ * When the DC advertises IPS support with IPS not fully disabled, self-refresh
+ * is supported and immediate vblank disable is configured, the enable path must
+ * call drm_crtc_vblank_restore() to estimate missed vblanks before arming the
+ * IRQs. The enable path then runs to completion.
+ */
+static void dm_test_crtc_enable_vblank_ips_restore(struct kunit *test)
+{
+	struct dm_crtc_state *acrtc_state;
+	struct drm_vblank_crtc *vblank;
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+	struct dc_link *link;
+
+	/* DCE_VERSION_8_0 supports VRR -> the vupdate-irq branch is walked. */
+	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_8_0);
+
+	/* OTG unassigned -> amdgpu_dm_crtc_set_vupdate_irq() returns 0 early. */
+	acrtc->otg_inst = -1;
+	acrtc_state = to_dm_crtc_state(acrtc->base.state);
+	acrtc_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
+
+	/* Non-NULL get_vblank_timestamp keeps drm_crtc_vblank_restore() quiet. */
+	acrtc->base.funcs = &dm_test_crtc_funcs;
+
+	/* IPS enabled and not fully disabled -> first restore condition holds. */
+	adev->dm.dc->caps.ips_support = true;
+	adev->dm.dc->config.disable_ips = DMUB_IPS_ENABLE;
+
+	/* Supported PSR version makes self-refresh supported. */
+	link = acrtc_state->stream->link;
+	link->psr_settings.psr_version = DC_PSR_VERSION_1;
+
+	/* Immediate vblank disable is the last condition gating the restore. */
+	vblank = drm_crtc_vblank_crtc(&acrtc->base);
+	vblank->config.disable_immediate = true;
+
+	adev->irq.installed = true;
+	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 1);
+	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 1);
+
+	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), 0);
+}
+
 /* Tests for amdgpu_dm_crtc_update_crtc_active_planes() */
 
 /**
@@ -1748,6 +1813,7 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_crtc_enable_vblank_crtc_irq_error),
 	KUNIT_CASE(dm_test_crtc_enable_vblank_in_reset),
 	KUNIT_CASE(dm_test_crtc_enable_vblank_queues_work),
+	KUNIT_CASE(dm_test_crtc_enable_vblank_ips_restore),
 	/* amdgpu_dm_crtc_update_crtc_active_planes */
 	KUNIT_CASE(dm_test_crtc_update_active_planes_no_stream),
 	/* amdgpu_dm_crtc_count_crtc_active_planes */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 28/41] drm/amd/display: Cover crtc vblank restore replay-supported path
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (24 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 27/41] drm/amd/display: Cover crtc vblank IPS self-refresh restore Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 29/41] drm/amd/display: Cover crtc destroy_state stream release Roman.Li
                   ` (13 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha

From: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>

Add dm_test_crtc_enable_vblank_ips_restore_replay to cover the
pr->config.replay_supported side of the sr_supported OR in
amdgpu_dm_crtc_set_vblank().

The existing IPS restore test establishes self-refresh support via the PSR
version. This test instead marks the PSR version unsupported and sets
replay_supported, forcing the sr_supported computation to fall through to
the replay branch while still calling drm_crtc_vblank_restore().

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 52 +++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index b64660064902..805c171564c8 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -1172,6 +1172,57 @@ static void dm_test_crtc_enable_vblank_ips_restore(struct kunit *test)
 	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), 0);
 }
 
+/**
+ * dm_test_crtc_enable_vblank_ips_restore_replay - Test IPS restore via replay support
+ * @test: The KUnit test context
+ *
+ * Same as dm_test_crtc_enable_vblank_ips_restore() but self-refresh support is
+ * established through replay rather than PSR: the PSR version is unsupported, so
+ * the sr_supported computation must fall through to pr->config.replay_supported.
+ * The enable path still calls drm_crtc_vblank_restore() and completes.
+ */
+static void dm_test_crtc_enable_vblank_ips_restore_replay(struct kunit *test)
+{
+	struct dm_crtc_state *acrtc_state;
+	struct drm_vblank_crtc *vblank;
+	struct amdgpu_device *adev;
+	struct amdgpu_crtc *acrtc;
+	struct dc_link *link;
+
+	/* DCE_VERSION_8_0 supports VRR -> the vupdate-irq branch is walked. */
+	acrtc = dm_test_crtc_setup_enable(test, &adev, DCE_VERSION_8_0);
+
+	/* OTG unassigned -> amdgpu_dm_crtc_set_vupdate_irq() returns 0 early. */
+	acrtc->otg_inst = -1;
+	acrtc_state = to_dm_crtc_state(acrtc->base.state);
+	acrtc_state->freesync_config.state = VRR_STATE_ACTIVE_VARIABLE;
+
+	/* Non-NULL get_vblank_timestamp keeps drm_crtc_vblank_restore() quiet. */
+	acrtc->base.funcs = &dm_test_crtc_funcs;
+
+	/* IPS enabled and not fully disabled -> first restore condition holds. */
+	adev->dm.dc->caps.ips_support = true;
+	adev->dm.dc->config.disable_ips = DMUB_IPS_ENABLE;
+
+	/*
+	 * PSR unsupported but replay supported -> sr_supported is driven by the
+	 * pr->config.replay_supported side of the OR.
+	 */
+	link = acrtc_state->stream->link;
+	link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED;
+	link->replay_settings.config.replay_supported = true;
+
+	/* Immediate vblank disable is the last condition gating the restore. */
+	vblank = drm_crtc_vblank_crtc(&acrtc->base);
+	vblank->config.disable_immediate = true;
+
+	adev->irq.installed = true;
+	dm_test_crtc_arm_irq_src(test, &adev->crtc_irq, 1);
+	dm_test_crtc_arm_irq_src(test, &adev->pageflip_irq, 1);
+
+	KUNIT_EXPECT_EQ(test, amdgpu_dm_crtc_enable_vblank(&acrtc->base), 0);
+}
+
 /* Tests for amdgpu_dm_crtc_update_crtc_active_planes() */
 
 /**
@@ -1814,6 +1865,7 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_crtc_enable_vblank_in_reset),
 	KUNIT_CASE(dm_test_crtc_enable_vblank_queues_work),
 	KUNIT_CASE(dm_test_crtc_enable_vblank_ips_restore),
+	KUNIT_CASE(dm_test_crtc_enable_vblank_ips_restore_replay),
 	/* amdgpu_dm_crtc_update_crtc_active_planes */
 	KUNIT_CASE(dm_test_crtc_update_active_planes_no_stream),
 	/* amdgpu_dm_crtc_count_crtc_active_planes */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 29/41] drm/amd/display: Cover crtc destroy_state stream release
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (25 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 28/41] drm/amd/display: Cover crtc vblank restore replay-supported path Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 30/41] drm/amd/display: Fix ABM over VABC Roman.Li
                   ` (12 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Bhawanpreet Lakha

From: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>

Add dm_test_crtc_destroy_state_releases_stream to cover the cur->stream
branch of amdgpu_dm_crtc_destroy_state(), complementing the existing
no-stream test.

The test attaches a DC stream to the CRTC state and takes an extra stream
reference so the destroy path drops back to the KUnit-managed reference
instead of freeing the stream, then verifies exactly one reference was
released.

Assisted-by: Copilot:Claude-Opus-4.8
Reviewed-by: Alex Hung <alex.hung@amd.com>
Signed-off-by: Bhawanpreet Lakha <bhawanpreet.lakha@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     | 35 +++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index 805c171564c8..4dacddd23878 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -1451,6 +1451,40 @@ static void dm_test_crtc_destroy_state_no_stream(struct kunit *test)
 	amdgpu_dm_crtc_destroy_state(NULL, &dm_state->base);
 }
 
+/**
+ * dm_test_crtc_destroy_state_releases_stream - Test destroy releases the stream
+ * @test: The KUnit test context
+ *
+ * When the CRTC state carries a DC stream, destroying the state must release a
+ * stream reference. An extra reference is taken up front so the release leaves
+ * the KUnit-managed reference intact rather than freeing the stream here.
+ */
+static void dm_test_crtc_destroy_state_releases_stream(struct kunit *test)
+{
+	struct dc_stream_state *stream;
+	struct dm_crtc_state *dm_state;
+	struct dc_link *link;
+
+	link = dm_kunit_alloc_link(test);
+	stream = dm_kunit_alloc_stream(test, link);
+
+	/*
+	 * Take an extra reference so amdgpu_dm_crtc_destroy_state() drops back to
+	 * the KUnit-managed reference instead of freeing the stream.
+	 */
+	kref_get(&stream->refcount);
+
+	/* destroy_state kfree()s the state, so use a plain (unmanaged) alloc. */
+	dm_state = kzalloc_obj(*dm_state, GFP_KERNEL);
+	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dm_state);
+	dm_state->stream = stream;
+
+	amdgpu_dm_crtc_destroy_state(NULL, &dm_state->base);
+
+	/* One reference was dropped, leaving the KUnit-managed one. */
+	KUNIT_EXPECT_EQ(test, kref_read(&stream->refcount), 1);
+}
+
 /**
  * dm_test_crtc_handle_vblank_no_event - Test vblank handling with no pending event
  * @test: The KUnit test context
@@ -1877,6 +1911,7 @@ static struct kunit_case amdgpu_dm_crtc_tests[] = {
 	KUNIT_CASE(dm_test_crtc_reset_state_allocates_state),
 	/* amdgpu_dm_crtc_destroy_state */
 	KUNIT_CASE(dm_test_crtc_destroy_state_no_stream),
+	KUNIT_CASE(dm_test_crtc_destroy_state_releases_stream),
 	/* amdgpu_dm_crtc_handle_vblank */
 	KUNIT_CASE(dm_test_crtc_handle_vblank_no_event),
 	KUNIT_CASE(dm_test_crtc_handle_vblank_skips_when_flip_submitted),
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 30/41] drm/amd/display: Fix ABM over VABC
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (26 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 29/41] drm/amd/display: Cover crtc destroy_state stream release Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 31/41] drm/amd/display: Add missing DCN42B register defines Roman.Li
                   ` (11 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Iswara Nagulendran,
	Anthony Koo

From: Iswara Nagulendran <Iswara.Nagulendran@amd.com>

[Why]
ABM does not take effect when brightness
is below twenty percent on VABC LCD panels.

[How]
Create new VESA aux path for brightness
translation functions. When VESA aux enabled
use zero-anchored linear interpolation to
translate instead of the legacy min max
backlight mapping.

Reviewed-by: Anthony Koo <anthony.koo@amd.com>
Signed-off-by: Iswara Nagulendran <Iswara.Nagulendran@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../drm/amd/display/modules/power/power_abm.c | 215 ++++++++++++++++--
 .../amd/display/modules/power/power_helpers.h |   9 +
 2 files changed, 210 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/modules/power/power_abm.c b/drivers/gpu/drm/amd/display/modules/power/power_abm.c
index b26ceaba940d..5e86889eaa84 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_abm.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_abm.c
@@ -245,29 +245,80 @@ struct iram_table_v_2_2 {
 #define MOD_POWER_TO_CORE(mod_power)\
 		container_of(mod_power, struct core_power, mod_public)
 
+/* Maximum brightness expressed in millipercent (100% * 1000). */
+#define BACKLIGHT_MILLIPERCENT_MAX (100 * 1000)
+
 static uint16_t backlight_8_to_16(unsigned int backlight_8bit)
 {
 	return (uint16_t)(backlight_8bit * 0x101);
 }
 
+/* Caches the link's backlight control type on the panel's backlight
+ * properties so the brightness translation helpers can pick the correct
+ * mapping.
+ */
+void mod_power_set_backlight_control_type(struct core_power *core_power,
+		unsigned int inst, enum backlight_control_type backlight_control_type)
+{
+	if (core_power == NULL)
+		return;
+
+	core_power->bl_prop[inst].backlight_control_type = backlight_control_type;
+}
+
+/* Returns true when the panel uses the VESA AUX backlight control path, which
+ * requires zero-anchored linear brightness interpolation.
+ */
+static bool is_vesa_abc(struct core_power *core_power, unsigned int inst)
+{
+	if (core_power == NULL)
+		return false;
+
+	return core_power->bl_prop[inst].backlight_control_type ==
+			BACKLIGHT_CONTROL_VESA_AUX;
+}
+
+/* Legacy millipercent→millinit conversion: scales linearly between
+ * [0%, 100%] → [min_brightness_millinits, max_brightness_millinits].
+ */
+static unsigned int backlight_millipercent_to_millinit_legacy(
+		struct core_power *core_power, unsigned int millipercent, unsigned int inst)
+{
+	if (core_power == NULL)
+		return 0;
+
+	return (unsigned int)div_u64((unsigned long long)millipercent *
+			core_power->bl_prop[inst].nits_range,
+			100000) +
+			core_power->bl_prop[inst].min_brightness_millinits;
+}
+
+/* Converts millipercent to millinit.
+ * For VESA AUX brightness control, uses simple linear interpolation with
+ * 0% = 0 nits and 100% = max_brightness_millinits.
+ * Otherwise, falls back to the legacy min→max nits range mapping.
+ */
 unsigned int backlight_millipercent_to_millinit(
 		struct core_power *core_power, unsigned int millipercent, unsigned int inst)
 {
-	unsigned int millinit = 0;
-	unsigned long long numerator = 0;
+	if (!is_vesa_abc(core_power, inst))
+		return backlight_millipercent_to_millinit_legacy(core_power, millipercent, inst);
 
 	if (core_power == NULL)
 		return 0;
 
-	numerator = ((unsigned long long)millipercent) *
-				core_power->bl_prop[inst].nits_range;
-	millinit = ((unsigned int)div_u64(numerator, 100000)) +
-			core_power->bl_prop[inst].min_brightness_millinits;
+	if (millipercent >= BACKLIGHT_MILLIPERCENT_MAX)
+		return core_power->bl_prop[inst].max_brightness_millinits;
 
-	return millinit;
+	return (unsigned int)div_u64((unsigned long long)millipercent *
+			core_power->bl_prop[inst].max_brightness_millinits,
+			BACKLIGHT_MILLIPERCENT_MAX);
 }
 
-static unsigned int backlight_millinit_to_millipercent(
+/* Legacy millinit→millipercent conversion: scales linearly between
+ * [min_brightness_millinits, max_brightness_millinits] → [0%, 100%].
+ */
+static unsigned int backlight_millinit_to_millipercent_legacy(
 		struct core_power *core_power, unsigned int millinit, unsigned int inst)
 {
 	unsigned int millipercent = 0;
@@ -280,7 +331,7 @@ static unsigned int backlight_millinit_to_millipercent(
 		return 0;
 
 	if (millinit >= core_power->bl_prop[inst].max_brightness_millinits)
-		return (100 * 1000);
+		return BACKLIGHT_MILLIPERCENT_MAX;
 
 	numerator = (((unsigned long long)millinit) -
 			core_power->bl_prop[inst].min_brightness_millinits) * 100000;
@@ -290,7 +341,31 @@ static unsigned int backlight_millinit_to_millipercent(
 	return millipercent;
 }
 
-static unsigned int backlight_pwm_to_millipercent(
+/* Converts millinit to millipercent.
+ * For VESA AUX brightness control, uses simple linear interpolation with
+ * 0 nits = 0% and max_brightness_millinits = 100%.
+ * Otherwise, falls back to the legacy min→max nits range mapping.
+ */
+static unsigned int backlight_millinit_to_millipercent(
+		struct core_power *core_power, unsigned int millinit, unsigned int inst)
+{
+	if (!is_vesa_abc(core_power, inst))
+		return backlight_millinit_to_millipercent_legacy(core_power, millinit, inst);
+
+	if (core_power == NULL)
+		return 0;
+
+	if (core_power->bl_prop[inst].max_brightness_millinits == 0)
+		return 0;
+
+	if (millinit >= core_power->bl_prop[inst].max_brightness_millinits)
+		return BACKLIGHT_MILLIPERCENT_MAX;
+
+	return (unsigned int)div_u64((unsigned long long)millinit * 100000,
+			core_power->bl_prop[inst].max_brightness_millinits);
+}
+
+static unsigned int backlight_pwm_to_millipercent_legacy(
 		struct core_power *core_power, unsigned int pwm, unsigned int inst)
 {
 	unsigned int millipercent = 0;
@@ -362,12 +437,37 @@ static unsigned int backlight_pwm_to_millipercent(
 	}
 
 	/* No interpolation, just take closest index */
-	millipercent = 1000 * 100 * mid / max_index;
+	millipercent = BACKLIGHT_MILLIPERCENT_MAX * mid / max_index;
 
 	return millipercent;
 }
 
-static unsigned int backlight_pwm_to_millinit(
+/* Converts PWM to millipercent.
+ * For VESA AUX brightness control, uses simple linear interpolation with
+ * 0 PWM = 0% and max_backlight_pwm = 100%.
+ * Otherwise, falls back to the legacy LUT based mapping.
+ */
+static unsigned int backlight_pwm_to_millipercent(
+		struct core_power *core_power, unsigned int pwm, unsigned int inst)
+{
+	if (!is_vesa_abc(core_power, inst))
+		return backlight_pwm_to_millipercent_legacy(core_power, pwm, inst);
+
+	if (core_power == NULL)
+		return 0;
+
+	if (core_power->bl_prop[inst].max_backlight_pwm == 0)
+		return 0;
+
+	if (pwm >= core_power->bl_prop[inst].max_backlight_pwm)
+		return BACKLIGHT_MILLIPERCENT_MAX;
+
+	return (unsigned int)div_u64((unsigned long long)pwm *
+			BACKLIGHT_MILLIPERCENT_MAX,
+			core_power->bl_prop[inst].max_backlight_pwm);
+}
+
+static unsigned int backlight_pwm_to_millinit_legacy(
 		struct core_power *core_power, unsigned int pwm, unsigned int inst)
 {
 	unsigned int millinit = 0;
@@ -394,7 +494,32 @@ static unsigned int backlight_pwm_to_millinit(
 	return millinit;
 }
 
-unsigned int backlight_millipercent_to_pwm(
+/* Converts PWM to millinit.
+ * For VESA AUX brightness control, uses simple linear interpolation with
+ * 0 PWM = 0 nits and max_backlight_pwm = max_brightness_millinits.
+ * Otherwise, falls back to the legacy min→max nits range mapping.
+ */
+static unsigned int backlight_pwm_to_millinit(
+		struct core_power *core_power, unsigned int pwm, unsigned int inst)
+{
+	if (!is_vesa_abc(core_power, inst))
+		return backlight_pwm_to_millinit_legacy(core_power, pwm, inst);
+
+	if (core_power == NULL)
+		return 0;
+
+	if (core_power->bl_prop[inst].max_backlight_pwm == 0)
+		return 0;
+
+	if (pwm >= core_power->bl_prop[inst].max_backlight_pwm)
+		return core_power->bl_prop[inst].max_brightness_millinits;
+
+	return (unsigned int)div_u64((unsigned long long)pwm *
+			core_power->bl_prop[inst].max_brightness_millinits,
+			core_power->bl_prop[inst].max_backlight_pwm);
+}
+
+static unsigned int backlight_millipercent_to_pwm_legacy(
 		struct core_power *core_power, unsigned int millipercent, unsigned int inst)
 {
 	unsigned int pwm = (unsigned int)-1;
@@ -431,7 +556,32 @@ unsigned int backlight_millipercent_to_pwm(
 	return pwm;
 }
 
-static unsigned int backlight_millinit_to_pwm(
+/* Converts millipercent to PWM.
+ * For VESA AUX brightness control, uses simple linear interpolation with
+ * 0% = 0 PWM and 100% = max_backlight_pwm.
+ * Otherwise, falls back to the legacy LUT based mapping.
+ */
+unsigned int backlight_millipercent_to_pwm(
+		struct core_power *core_power, unsigned int millipercent, unsigned int inst)
+{
+	if (!is_vesa_abc(core_power, inst))
+		return backlight_millipercent_to_pwm_legacy(core_power, millipercent, inst);
+
+	if (core_power == NULL)
+		return 0;
+
+	if (millipercent >= BACKLIGHT_MILLIPERCENT_MAX)
+		return core_power->bl_prop[inst].max_backlight_pwm;
+
+	return (unsigned int)div_u64((unsigned long long)millipercent *
+			core_power->bl_prop[inst].max_backlight_pwm,
+			BACKLIGHT_MILLIPERCENT_MAX);
+}
+
+/* Legacy millinit→PWM conversion: scales linearly between
+ * [min_brightness_millinits, max_brightness_millinits] → [min_backlight_pwm, max_backlight_pwm].
+ */
+static unsigned int backlight_millinit_to_pwm_legacy(
 		struct core_power *core_power, unsigned int millinit, unsigned int inst)
 {
 	unsigned int pwm = 0;
@@ -460,6 +610,35 @@ static unsigned int backlight_millinit_to_pwm(
 	return pwm;
 }
 
+/* Converts millinit to PWM.
+ * For VESA AUX brightness control, uses simple linear interpolation with
+ * 0 nits = 0 PWM and max_brightness_millinits = max_backlight_pwm.
+ * Otherwise, falls back to the legacy min→max nits range mapping.
+ */
+static unsigned int backlight_millinit_to_pwm(
+		struct core_power *core_power, unsigned int millinit, unsigned int inst)
+{
+	if (!is_vesa_abc(core_power, inst))
+		return backlight_millinit_to_pwm_legacy(core_power, millinit, inst);
+
+	if (core_power == NULL)
+		return 0;
+
+	if (core_power->bl_prop[inst].max_brightness_millinits == 0)
+		return 0;
+
+	if (millinit >= core_power->bl_prop[inst].max_brightness_millinits)
+		return core_power->bl_prop[inst].max_backlight_pwm;
+
+	/* millinit is bounded by max_brightness_millinits (up to ~10^7 for ~10000 nits).
+	 * max_backlight_pwm is a 32-bit value.
+	 * Worst-case product (~10^7 × UINT_MAX ≈ 4×10^16) fits within unsigned long long.
+	 */
+	return (unsigned int)div_u64((unsigned long long)millinit *
+			core_power->bl_prop[inst].max_backlight_pwm,
+			core_power->bl_prop[inst].max_brightness_millinits);
+}
+
 static bool validate_ext_backlight_caps(
 		struct dm_acpi_atif_backlight_caps *ext_backlight_caps)
 {
@@ -716,6 +895,14 @@ void mod_power_update_backlight_on_mode_change(
 {
     struct set_backlight_level_params backlight_level_params = { 0 };
 
+		/* Cache the panel's backlight control type once at mode-change/init
+		 * time. It is a stable per-panel property (decided in the OS shim
+		 * from panel type + DPCD caps), so the brightness translation
+		 * helpers can read it without it being passed on every call.
+		 */
+		mod_power_set_backlight_control_type(core_power, panel_inst,
+				link->backlight_control_type);
+
 		if ((link->dpcd_sink_ext_caps.bits.hdr_aux_backlight_control == 1 ||
 			link->dpcd_sink_ext_caps.bits.sdr_aux_backlight_control == 1) &&
 			link->backlight_control_type == BACKLIGHT_CONTROL_AMD_AUX)
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
index 548c8ff6ddb4..68679fa10946 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
+++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
@@ -102,6 +102,13 @@ struct pwr_backlight_properties {
 	unsigned int max_brightness_millinits;
 	unsigned int nits_range;
 
+	/* Backlight control type of the associated link. Cached here so the
+	 * brightness translation helpers can select the correct mapping
+	 * (legacy vs. VESA AUX zero-anchored) without threading the type
+	 * through every call.
+	 */
+	enum backlight_control_type backlight_control_type;
+
 	bool backlight_caps_valid;
 	bool use_custom_backlight_caps;
 	unsigned int custom_backlight_caps_config_no;
@@ -190,6 +197,8 @@ void reset_replay_dsync_error_count(struct dc_link *link);
 void change_replay_to_psr(struct dc_link *link);
 void change_psr_to_replay(struct dc_link *link);
 void initialize_backlight_caps(struct core_power *core_power, unsigned int inst);
+void mod_power_set_backlight_control_type(struct core_power *core_power,
+		unsigned int inst, enum backlight_control_type backlight_control_type);
 unsigned int backlight_millipercent_to_pwm(
 		struct core_power *core_power, unsigned int millipercent, unsigned int inst);
 unsigned int backlight_millipercent_to_millinit(
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 31/41] drm/amd/display: Add missing DCN42B register defines
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (27 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 30/41] drm/amd/display: Fix ABM over VABC Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 32/41] drm/amd/display: Add missing DMUB CACP and PR definitions Roman.Li
                   ` (10 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Matthew Stewart, Ovidiu Bunea

From: Matthew Stewart <Matthew.Stewart2@amd.com>

[why]

These registers are used, but were missing from their corresponding lists.

Reviewed-by: Ovidiu (Ovi) Bunea <ovidiu.bunea@amd.com>
Signed-off-by: Matthew Stewart <Matthew.Stewart2@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../hpo/dcn31/dcn31_hpo_dp_stream_encoder.h   | 47 -------------------
 .../dc/resource/dcn42b/dcn42b_resource.c      | 19 +++++++-
 2 files changed, 17 insertions(+), 49 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.h
index 66739c643e2f..d96fcc59cc0e 100644
--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.h
@@ -165,53 +165,6 @@
 	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL, CRC_CONT_MODE_ENABLE, mask_sh),\
 	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_HBLANK_CONTROL, HBLANK_MINIMUM_SYMBOL_WIDTH, mask_sh)
 
-/* Not in DCN42B:
- * SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL, CRC_ENABLE, mask_sh),
- * SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL, CRC_CONT_MODE_ENABLE, mask_sh),
- * SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_HBLANK_CONTROL, HBLANK_MINIMUM_SYMBOL_WIDTH, mask_sh),
- */
-#define DCN4_2B_HPO_DP_STREAM_ENC_MASK_SH_LIST(mask_sh)\
-	SE_SF(DP_STREAM_MAPPER_CONTROL0, DP_STREAM_LINK_TARGET, mask_sh),\
-	SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_CONTROL, DP_STREAM_ENC_CLOCK_EN, mask_sh),\
-	SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_INPUT_MUX_CONTROL, DP_STREAM_ENC_INPUT_MUX_PIXEL_STREAM_SOURCE_SEL, mask_sh),\
-	SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, mask_sh),\
-	SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC_APG_CLOCK_EN, mask_sh),\
-	SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET, mask_sh),\
-	SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_RESET_DONE, mask_sh),\
-	SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, FIFO_ENABLE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_CONTROL, DP_SYM32_ENC_RESET, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_CONTROL, DP_SYM32_ENC_RESET_DONE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_CONTROL, DP_SYM32_ENC_ENABLE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT, PIXEL_ENCODING_TYPE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT, UNCOMPRESSED_PIXEL_ENCODING, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT, UNCOMPRESSED_COMPONENT_DEPTH, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, PIXEL_FORMAT_DOUBLE_BUFFER_ENABLE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, MSA_DOUBLE_BUFFER_ENABLE, mask_sh),\
-	SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_0, mask_sh),\
-	SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_1, mask_sh),\
-	SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_2, mask_sh),\
-	SE_SF(DP_SYM32_ENC_VID_MSA, MSA_DATA_LANE_3, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_FIFO_CONTROL, PIXEL_TO_SYMBOL_FIFO_RESET, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_FIFO_CONTROL, PIXEL_TO_SYMBOL_FIFO_RESET_DONE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_FIFO_CONTROL, PIXEL_TO_SYMBOL_FIFO_ENABLE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_STREAM_CONTROL, VID_STREAM_ENABLE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_STREAM_CONTROL, VID_STREAM_STATUS, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_VBID_CONTROL, VBID_6_COMPRESSEDSTREAM_FLAG_SOF_REFERENCE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_VID_VBID_CONTROL, VBID_6_COMPRESSEDSTREAM_FLAG_LINE_NUMBER, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_CONTROL, SDP_STREAM_ENABLE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_PAYLOAD_SIZE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL0, GSP_TRANSMISSION_LINE_NUMBER, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_VIDEO_CONTINUOUS_TRANSMISSION_ENABLE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_TRANSMISSION_LINE_NUMBER, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_GSP_CONTROL5, GSP_SOF_REFERENCE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, METADATA_PACKET_ENABLE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, AUDIO_MUTE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ASP_ENABLE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ATP_ENABLE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, AIP_ENABLE, mask_sh),\
-	SE_SF(DP_SYM32_ENC0_DP_SYM32_ENC_SDP_AUDIO_CONTROL0, ACM_ENABLE, mask_sh)
-
 
 #define DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(type) \
 	type DP_STREAM_LINK_TARGET;\
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c
index dbd6267340ac..7b14d67314d5 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c
@@ -148,6 +148,21 @@
 #define regDP_SYM32_ENC2_DP_SYM32_ENC_HBLANK_CONTROL                                                    0x3813
 #define regDP_SYM32_ENC2_DP_SYM32_ENC_HBLANK_CONTROL_BASE_IDX                                           2
 
+#define DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL__CRC_ENABLE__SHIFT                                         0x0
+#define DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL__CRC_CONT_MODE_ENABLE__SHIFT                               0x4
+#define DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL__CRC_ENABLE_MASK                                           0x00000001L
+#define DP_SYM32_ENC0_DP_SYM32_ENC_VID_CRC_CONTROL__CRC_CONT_MODE_ENABLE_MASK                                 0x00000010L
+#define DP_SYM32_ENC0_DP_SYM32_ENC_HBLANK_CONTROL__HBLANK_MINIMUM_SYMBOL_WIDTH__SHIFT                         0x0
+#define DP_SYM32_ENC0_DP_SYM32_ENC_HBLANK_CONTROL__HBLANK_MINIMUM_SYMBOL_WIDTH_MASK                           0x0000FFFFL
+
+
+#define DP_SYM32_ENC1_DP_SYM32_ENC_VID_CRC_CONTROL__CRC_ENABLE__SHIFT                                         0x0
+#define DP_SYM32_ENC1_DP_SYM32_ENC_VID_CRC_CONTROL__CRC_CONT_MODE_ENABLE__SHIFT                               0x4
+#define DP_SYM32_ENC1_DP_SYM32_ENC_VID_CRC_CONTROL__CRC_ENABLE_MASK                                           0x00000001L
+#define DP_SYM32_ENC1_DP_SYM32_ENC_VID_CRC_CONTROL__CRC_CONT_MODE_ENABLE_MASK                                 0x00000010L
+#define DP_SYM32_ENC1_DP_SYM32_ENC_HBLANK_CONTROL__HBLANK_MINIMUM_SYMBOL_WIDTH__SHIFT                         0x0
+#define DP_SYM32_ENC1_DP_SYM32_ENC_HBLANK_CONTROL__HBLANK_MINIMUM_SYMBOL_WIDTH_MASK                           0x0000FFFFL
+
 enum dcn401_clk_src_array_id {
 	DCN401_CLK_SRC_PLL0,
 	DCN401_CLK_SRC_PLL1,
@@ -370,10 +385,10 @@ static const struct dcn10_link_enc_mask le_mask = {
 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_2B_HPO_DP_STREAM_ENC_MASK_SH_LIST(__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_2B_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK)};
+	DCN4_2_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK)};
 
 #define hpo_dp_link_encoder_reg_init(id) \
 	DCN42B_HPO_DP_LINK_ENC_REG_LIST_RI(id)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 32/41] drm/amd/display: Add missing DMUB CACP and PR definitions
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (28 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 31/41] drm/amd/display: Add missing DCN42B register defines Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 33/41] drm/amd/display: Add missing OTG_CRC1_SELECT mask for DCN3.2 Roman.Li
                   ` (9 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Taimur Hassan

From: Taimur Hassan <Syed.Hassan@amd.com>

[Why]
Should have been picked up in 0.1.69.0 promotion commit.

[How]
Add the missing DMUB command-header definitions in dmub_cmd.h:

1. DMUB_CMD__CACP_GET_ACE_CURVE_AREA command ID.
2. Request/response data and command structs.
3. PR runtime flag bit.

Signed-off-by: Taimur Hassan <Syed.Hassan@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
Reviewed-by: Alex Hung <alex.hung@amd.com>
---
 .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
index 44aefa3608ec..f0231f355fa7 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -6256,6 +6256,10 @@ enum dmub_cmd_cacp_type {
 	 * Get CACP Histogram
 	 */
 	DMUB_CMD__CACP_GET_HISTOGRAM = 7,
+	/**
+	 * Get ACE curve area for IGT test validation.
+	 */
+	DMUB_CMD__CACP_GET_ACE_CURVE_AREA = 8,
 };
 
 /**
@@ -6644,6 +6648,50 @@ struct dmub_rb_cmd_cacp_get_histogram {
 	uint8_t pad;
 };
 
+/**
+ * Data passed from driver to FW in a DMUB_CMD__CACP_GET_ACE_CURVE_AREA command.
+ */
+struct dmub_cmd_cacp_get_ace_curve_area_in {
+	/**
+	 * eDP panel instance (0-based).
+	 */
+	uint8_t panel_inst;
+	/**
+	 * Explicit padding to 4 byte boundary.
+	 */
+	uint8_t pad[3];
+};
+
+/**
+ * Data returned from FW in a DMUB_CMD__CACP_GET_ACE_CURVE_AREA command.
+ */
+struct dmub_cmd_cacp_get_ace_curve_area_out {
+	/**
+	 * Computed area under the ACE PWL curve (trapezoidal integration).
+	 * Lower value = stronger dimming (higher CACP level).
+	 * Directly comparable across levels.
+	 */
+	uint32_t area;
+};
+
+/**
+ * Definition of a DMUB_CMD__CACP_GET_ACE_CURVE_AREA command.
+ * Uses inline response pattern: input and output share the data union.
+ */
+struct dmub_rb_cmd_cacp_get_ace_curve_area {
+	/**
+	 * Command header.
+	 */
+	struct dmub_cmd_header header;
+	/**
+	 * Data union for input/output.
+	 */
+	union {
+		struct dmub_cmd_cacp_get_ace_curve_area_in in;
+		struct dmub_cmd_cacp_get_ace_curve_area_out out;
+	} data;
+};
+
 /**
  * Data passed from driver to FW in a DMUB_CMD__QUERY_FEATURE_CAPS command.
  */
@@ -7435,6 +7483,7 @@ struct dmub_rb_cmd_pr_copy_settings {
 union dmub_pr_runtime_flags {
 	struct {
 		uint32_t disable_abm_optimization : 1; // Disable ABM optimization for PR
+		uint32_t abm_periodic_ffu_allowed : 1; // DAL: scenario wants periodic ABM keep-alive FFU
 	} bitfields;
 	uint32_t u32All;
 };
@@ -7815,6 +7864,11 @@ union dmub_rb_cmd {
 	 */
 	struct dmub_rb_cmd_cacp_get_histogram cacp_get_histogram;
 
+	/**
+	 * Definition of a DMUB_CMD__CACP_GET_ACE_CURVE_AREA command.
+	 */
+	struct dmub_rb_cmd_cacp_get_ace_curve_area cacp_get_ace_curve_area;
+
 	/**
 	 * Definition of a DMUB_CMD__IDLE_OPT_DCN_NOTIFY_IDLE command.
 	 */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 33/41] drm/amd/display: Add missing OTG_CRC1_SELECT mask for DCN3.2
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (29 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 32/41] drm/amd/display: Add missing DMUB CACP and PR definitions Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 34/41] drm/amd/display: Fix CRC engine 1 enable/disable on DCN3.1.2+ Roman.Li
                   ` (8 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Wayne Lin

From: Wayne Lin <Wayne.Lin@amd.com>

[Why]
Configuring CRC engine 1 via optc35_configure_crc() triggers
ASSERT(mask != 0) in dc_helper.c when programming OTG_CRC1_SELECT.
The DCN3.2 OPTC mask list inherited from dcn32 is missing this field,
so ROI[1] CRC cannot be enabled in DisplayCRC mode on DCN3.5/3.51.

[How]
Add OTG_CRC1_SELECT to OPTC_COMMON_MASK_SH_LIST_DCN3_2, matching the
existing dcn10 definition so REG_UPDATE can program CRC engine 1.

Reviewed-by: ChiaHsuan (Tom) Chung <chiahsuan.chung@amd.com>
Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
index ead92ad78a23..7df1ed1102d6 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
@@ -132,6 +132,7 @@
 	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_CRC1_SELECT, mask_sh),\
 	SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 34/41] drm/amd/display: Fix CRC engine 1 enable/disable on DCN3.1.2+
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (30 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 33/41] drm/amd/display: Add missing OTG_CRC1_SELECT mask for DCN3.2 Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 35/41] drm/amd/display: Configure all CRC engines in pipe CRC source path Roman.Li
                   ` (7 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Wayne Lin

From: Wayne Lin <Wayne.Lin@amd.com>

[Why]
Multi-ROI CRC uses OTG_CRC1_EN for the second engine, but the driver
only toggled OTG_CRC_EN and cleared the whole OTG_CRC_CNTL register on
disable.

[How]
Program engine 1 via OTG_CRC1_EN where supported, disable each
engine independently by crc_eng_inst, and add the missing mask on
relevant DCN ASICs.

Reviewed-by: ChiaHsuan (Tom) Chung <chiahsuan.chung@amd.com>
Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../amd/display/dc/optc/dcn10/dcn10_optc.c    | 36 +++++++++++++++----
 .../amd/display/dc/optc/dcn10/dcn10_optc.h    |  3 +-
 .../amd/display/dc/optc/dcn31/dcn31_optc.h    |  4 +++
 .../amd/display/dc/optc/dcn314/dcn314_optc.h  |  1 +
 .../amd/display/dc/optc/dcn32/dcn32_optc.h    |  1 +
 .../amd/display/dc/optc/dcn35/dcn35_optc.c    | 26 +++++++++++---
 .../amd/display/dc/optc/dcn401/dcn401_optc.h  |  1 +
 .../amd/display/dc/optc/dcn42/dcn42_optc.c    |  5 ++-
 .../amd/display/dc/optc/dcn42/dcn42_optc.h    |  2 ++
 .../dc/resource/dcn315/dcn315_resource.c      |  4 +--
 .../dc/resource/dcn316/dcn316_resource.c      |  4 +--
 11 files changed, 69 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c
index cf8e22289d6a..844705a0e32d 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c
@@ -1471,8 +1471,21 @@ bool optc1_configure_crc(struct timing_generator *optc,
 	if (!optc1_is_tg_enabled(optc))
 		return false;
 
-	if (!params->enable || params->reset)
-		REG_WRITE(OTG_CRC_CNTL, 0);
+	if (!params->enable || params->reset) {
+		switch (params->crc_eng_inst) {
+		case 0:
+			REG_UPDATE(OTG_CRC_CNTL, OTG_CRC_EN, 0);
+			break;
+		case 1:
+			if (optc1->tg_mask->OTG_CRC1_EN != 0)
+				REG_UPDATE(OTG_CRC_CNTL, OTG_CRC1_EN, 0);
+			else
+				REG_UPDATE(OTG_CRC_CNTL, OTG_CRC_EN, 0);
+			break;
+		default:
+			return false;
+		}
+	}
 
 	if (!params->enable)
 		return true;
@@ -1528,10 +1541,16 @@ bool optc1_configure_crc(struct timing_generator *optc,
 				OTG_CRC1_WINDOWB_Y_END, params->windowb_y_end);
 
 		/* Set crc mode and selection, and enable.*/
-		REG_UPDATE_3(OTG_CRC_CNTL,
-				OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
-				OTG_CRC1_SELECT, params->selection,
-				OTG_CRC_EN, 1);
+		if (optc1->tg_mask->OTG_CRC1_EN != 0)
+			REG_UPDATE_3(OTG_CRC_CNTL,
+					OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
+					OTG_CRC1_SELECT, params->selection,
+					OTG_CRC1_EN, 1);
+		else
+			REG_UPDATE_3(OTG_CRC_CNTL,
+					OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
+					OTG_CRC1_SELECT, params->selection,
+					OTG_CRC_EN, 1);
 		break;
 	default:
 		return false;
@@ -1562,7 +1581,10 @@ bool optc1_get_crc(struct timing_generator *optc, uint8_t idx,
 	uint32_t field = 0;
 	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 
-	REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field);
+	if (idx == 1 && optc1->tg_mask->OTG_CRC1_EN != 0)
+		REG_GET(OTG_CRC_CNTL, OTG_CRC1_EN, &field);
+	else
+		REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field);
 
 	/* Early return if CRC is not enabled for this CRTC */
 	if (!field)
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h
index bceefb5320eb..d099e05c7207 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h
@@ -655,7 +655,8 @@ struct dcn_optc_registers {
 	type OTG0_IHC_OTG_VERTICAL_INTERRUPT2_DEST;
 
 #define TG_REG_FIELD_LIST_DCN3_2(type) \
-	type OTG_H_TIMING_DIV_MODE_MANUAL;
+	type OTG_H_TIMING_DIV_MODE_MANUAL;\
+	type OTG_CRC1_EN;
 
 #define TG_REG_FIELD_LIST_DCN3_5(type) \
 	type OTG_CRC0_WINDOWA_X_START_READBACK;\
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h
index 98f7d2e299c5..119a954fe3e5 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.h
@@ -263,6 +263,10 @@
 	SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_VUPDATE_KEEPOUT_STATUS, mask_sh),\
 	SF(OTG0_INTERRUPT_DEST, OTG0_IHC_OTG_VERTICAL_INTERRUPT2_DEST, mask_sh)
 
+#define OPTC_COMMON_MASK_SH_LIST_DCN31X(mask_sh)\
+	OPTC_COMMON_MASK_SH_LIST_DCN3_1(mask_sh),\
+	SF(OTG0_OTG_CRC_CNTL, OTG_CRC1_EN, mask_sh)
+
 void dcn31_timing_generator_init(struct optc *optc1);
 
 bool optc31_immediate_disable_crtc(struct timing_generator *optc);
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.h
index 6bfdee3fcf5f..7b43c3ecd46b 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.h
@@ -205,6 +205,7 @@
 	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_CRC_CNTL, OTG_CRC1_EN, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
index 7df1ed1102d6..60c01ec28b65 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
@@ -134,6 +134,7 @@
 	SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\
 	SF(OTG0_OTG_CRC_CNTL, OTG_CRC1_SELECT, mask_sh),\
 	SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\
+	SF(OTG0_OTG_CRC_CNTL, OTG_CRC1_EN, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
index 9b7f9d5bbfb3..897f857db448 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c
@@ -205,7 +205,10 @@ static bool optc35_get_crc(struct timing_generator *optc, uint8_t idx,
 	uint32_t field = 0;
 	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 
-	REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field);
+	if (idx == 1 && optc1->tg_mask->OTG_CRC1_EN != 0)
+		REG_GET(OTG_CRC_CNTL, OTG_CRC1_EN, &field);
+	else
+		REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field);
 
 	/* Early return if CRC is not enabled for this CRTC */
 	if (!field)
@@ -275,8 +278,21 @@ bool optc35_configure_crc(struct timing_generator *optc,
 	if (!optc1_is_tg_enabled(optc))
 		return false;
 
-	if (!params->enable || params->reset)
-		REG_WRITE(OTG_CRC_CNTL, 0);
+	if (!params->enable || params->reset) {
+		switch (params->crc_eng_inst) {
+		case 0:
+			REG_UPDATE(OTG_CRC_CNTL, OTG_CRC_EN, 0);
+			break;
+		case 1:
+			if (optc1->tg_mask->OTG_CRC1_EN != 0)
+				REG_UPDATE(OTG_CRC_CNTL, OTG_CRC1_EN, 0);
+			else
+				REG_UPDATE(OTG_CRC_CNTL, OTG_CRC_EN, 0);
+			break;
+		default:
+			return false;
+		}
+	}
 
 	if (!params->enable)
 		return true;
@@ -341,13 +357,13 @@ bool optc35_configure_crc(struct timing_generator *optc,
 			REG_UPDATE_4(OTG_CRC_CNTL,
 					OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
 					OTG_CRC1_SELECT, params->selection,
-					OTG_CRC_EN, 1,
+					OTG_CRC1_EN, 1,
 					OTG_CRC_WINDOW_DB_EN, 1);
 		else
 			REG_UPDATE_3(OTG_CRC_CNTL,
 					OTG_CRC_CONT_EN, params->continuous_mode ? 1 : 0,
 					OTG_CRC1_SELECT, params->selection,
-					OTG_CRC_EN, 1);
+					OTG_CRC1_EN, 1);
 		break;
 	default:
 		return false;
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h
index fa62737b5b1b..3add972ca2ff 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.h
@@ -111,6 +111,7 @@
 	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_CRC_CNTL, OTG_CRC1_EN, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_RG, CRC0_R_CR, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_RG, CRC0_G_Y, mask_sh),\
 	SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\
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
index 4370d64259e7..fd9c2b6b8b3c 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c
@@ -46,7 +46,10 @@ bool optc42_get_crc(struct timing_generator *optc, uint8_t idx,
 	uint32_t field = 0;
 	struct optc *optc1 = DCN10TG_FROM_TG(optc);
 
-	REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field);
+	if (idx == 1 && optc1->tg_mask->OTG_CRC1_EN != 0)
+		REG_GET(OTG_CRC_CNTL, OTG_CRC1_EN, &field);
+	else
+		REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field);
 
 	/* Early return if CRC is not enabled for this CRTC */
 	if (!field)
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
index 758cddd9e64f..bc641f6ecd7e 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h
@@ -138,6 +138,7 @@
 	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_CRC_CNTL, OTG_CRC1_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),\
@@ -316,6 +317,7 @@
 	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_CRC_CNTL, OTG_CRC1_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),\
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
index 7c78f8ba40ef..470f3bd37314 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
@@ -659,11 +659,11 @@ static const struct dcn_optc_registers optc_regs[] = {
 };
 
 static const struct dcn_optc_shift optc_shift = {
-	OPTC_COMMON_MASK_SH_LIST_DCN3_1(__SHIFT)
+	OPTC_COMMON_MASK_SH_LIST_DCN31X(__SHIFT)
 };
 
 static const struct dcn_optc_mask optc_mask = {
-	OPTC_COMMON_MASK_SH_LIST_DCN3_1(_MASK)
+	OPTC_COMMON_MASK_SH_LIST_DCN31X(_MASK)
 };
 
 #define hubp_regs(id)\
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
index b9d2567a4180..d81d241901b4 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
@@ -654,11 +654,11 @@ static const struct dcn_optc_registers optc_regs[] = {
 };
 
 static const struct dcn_optc_shift optc_shift = {
-	OPTC_COMMON_MASK_SH_LIST_DCN3_1(__SHIFT)
+	OPTC_COMMON_MASK_SH_LIST_DCN31X(__SHIFT)
 };
 
 static const struct dcn_optc_mask optc_mask = {
-	OPTC_COMMON_MASK_SH_LIST_DCN3_1(_MASK)
+	OPTC_COMMON_MASK_SH_LIST_DCN31X(_MASK)
 };
 
 #define hubp_regs(id)\
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 35/41] drm/amd/display: Configure all CRC engines in pipe CRC source path
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (31 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 34/41] drm/amd/display: Fix CRC engine 1 enable/disable on DCN3.1.2+ Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 36/41] drm/amd/display: Fix more KUnit connector use-after-free bugs Roman.Li
                   ` (6 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Wayne Lin

From: Wayne Lin <Wayne.Lin@amd.com>

Iterate every CRC engine instance when enabling or disabling the pipe CRC
source so DCN31x OTG_CRC1_EN is handled alongside OTG_CRC_EN, matching the
legacy shared enable behavior used by DisplayCRC multi-ROI.

Reviewed-by: ChiaHsuan (Tom) Chung <chiahsuan.chung@amd.com>
Signed-off-by: Wayne Lin <Wayne.Lin@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c   | 13 +++++++++----
 drivers/gpu/drm/amd/display/dc/dc_types.h           |  3 ++-
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
index 05387bedf24a..db546dd44b91 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c
@@ -604,10 +604,15 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
 
 	/* Enable or disable CRTC CRC generation */
 	if (dm_is_crc_source_crtc(source) || source == AMDGPU_DM_PIPE_CRC_SOURCE_NONE) {
-		if (!dc_stream_configure_crc(stream_state->ctx->dc,
-					     stream_state, NULL, enable, enable, 0, true, crc_poly_mode)) {
-			ret = -EINVAL;
-			goto unlock;
+		int i;
+
+		for (i = 0; i < MAX_CRC_WINDOW_NUM; i++) {
+			if (!dc_stream_configure_crc(stream_state->ctx->dc,
+						     stream_state, NULL, enable, enable,
+						     i, true, crc_poly_mode)) {
+				ret = -EINVAL;
+				goto unlock;
+			}
 		}
 	}
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index b14d882e08d4..7da673111ed9 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -1045,9 +1045,10 @@ enum backlight_control_type {
 	BACKLIGHT_CONTROL_AMD_AUX = 2,
 };
 
-#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
 #define MAX_CRC_WINDOW_NUM	2
 
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+
 struct otg_phy_mux {
 	uint8_t phy_output_num;
 	uint8_t otg_output_num;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 36/41] drm/amd/display: Fix more KUnit connector use-after-free bugs
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (32 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 35/41] drm/amd/display: Configure all CRC engines in pipe CRC source path Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 37/41] drm/amd/display: Update BW bounding box unconditionally for DCN6 Roman.Li
                   ` (5 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen

From: Alex Hung <alex.hung@amd.com>

drmm_connector_init() and drmm_encoder_init() register their cleanup
(drm_connector_cleanup() / drm_encoder_cleanup()) as DRM-managed actions
tied to the drm_device lifetime. When the object memory is owned by
KUnit, it is freed before that action runs, so the cleanup touches freed
memory. Allocate these objects with drmm_kzalloc() so their lifetime
matches the cleanup action.

Signed-off-by: Alex Hung <alex.hung@amd.com>
Assisted-by: Copilot:Claude-Opus-4.8
---
 .../display/amdgpu_dm/tests/amdgpu_dm_connector_test.c    | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
index 1658d4d5997a..a54fd9529dc9 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_connector_test.c
@@ -3763,7 +3763,7 @@ static struct dm_test_stream_ctx *dm_test_stream_ctx_alloc(struct kunit *test)
 						       DRIVER_MODESET);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->drm);
 
-	ctx->aconnector = kunit_kzalloc(test, sizeof(*ctx->aconnector), GFP_KERNEL);
+	ctx->aconnector = drmm_kzalloc(ctx->drm, sizeof(*ctx->aconnector), GFP_KERNEL);
 	KUNIT_ASSERT_NOT_NULL(test, ctx->aconnector);
 	KUNIT_ASSERT_EQ(test,
 		drmm_connector_init(ctx->drm, &ctx->aconnector->base,
@@ -4026,7 +4026,7 @@ static void dm_test_poll_dac_load_returns_cached(struct kunit *test)
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
 	adev = drm_to_adev(drm);
 
-	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+	aconnector = drmm_kzalloc(drm, sizeof(*aconnector), GFP_KERNEL);
 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
 	KUNIT_ASSERT_EQ(test,
 		drmm_connector_init(drm, &aconnector->base,
@@ -4073,7 +4073,7 @@ static struct amdgpu_dm_connector *dm_test_reg_connector(struct kunit *test)
 						  DRIVER_MODESET);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm);
 
-	aconnector = kunit_kzalloc(test, sizeof(*aconnector), GFP_KERNEL);
+	aconnector = drmm_kzalloc(drm, sizeof(*aconnector), GFP_KERNEL);
 	KUNIT_ASSERT_NOT_NULL(test, aconnector);
 	KUNIT_ASSERT_EQ(test,
 		drmm_connector_init(drm, &aconnector->base,
@@ -4528,7 +4528,7 @@ dm_test_modes_ctx_alloc(struct kunit *test, int connector_type)
 	ctx->drm = dm_test_alloc_drm(test);
 	ctx->aconnector = dm_test_add_connector(test, ctx->drm, connector_type);
 
-	ctx->aenc = kunit_kzalloc(test, sizeof(*ctx->aenc), GFP_KERNEL);
+	ctx->aenc = drmm_kzalloc(ctx->drm, sizeof(*ctx->aenc), GFP_KERNEL);
 	KUNIT_ASSERT_NOT_NULL(test, ctx->aenc);
 	KUNIT_ASSERT_EQ(test,
 			drmm_encoder_init(ctx->drm, &ctx->aenc->base, NULL,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 37/41] drm/amd/display: Update BW bounding box unconditionally for DCN6
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (33 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 36/41] drm/amd/display: Fix more KUnit connector use-after-free bugs Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:12 ` [PATCH 38/41] drm/amd/display: switch max FFE level cap based on FRL link rate Roman.Li
                   ` (4 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Alvin Lee, Dillon Varone

From: Alvin Lee <Alvin.Lee2@amd.com>

[Description]
DCN6 needs to update BW bounding box in hw init in order to propagate
the Alt-Ch aperture info into DML. In this case update unconditionally
on dcn6 HW init.

Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c
index 05239e2f086f..72c2d3ca52f6 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c
@@ -548,7 +548,6 @@ void dcn60_init_hw(struct dc *dc)
 	unsigned 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);
@@ -589,8 +588,6 @@ void dcn60_init_hw(struct dc *dc)
 				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);
@@ -764,9 +761,8 @@ void dcn60_init_hw(struct dc *dc)
 		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->res_pool->funcs->update_bw_bounding_box) {
+			/* For DCN6 re-update unconditionally to propagate Alt-Ch address info into DML */
 			if (dc->clk_mgr)
 				dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
 		}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 38/41] drm/amd/display: switch max FFE level cap based on FRL link rate
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (34 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 37/41] drm/amd/display: Update BW bounding box unconditionally for DCN6 Roman.Li
@ 2026-07-31 21:12 ` Roman.Li
  2026-07-31 21:13 ` [PATCH 39/41] drm/amd/display: Add FFE level defaults Roman.Li
                   ` (3 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:12 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Relja Vojvodic,
	Nicholas Kazlauskas

From: Relja Vojvodic <Relja.Vojvodic@amd.com>

[How & Why]
- Add support for dynamic FFE levels based on debug config and link rate

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Relja Vojvodic <Relja.Vojvodic@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 .../gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.c  | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.c
index 86ac881879cf..6fe15324ea50 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.c
@@ -139,7 +139,8 @@ void dpcs60_program_eq_setting(
 		bool no_ffe,
 		const struct dc_hdmi_frl_link_settings *link_settings)
 {
-	const uint8_t max_ffe_level = 0x7;
+	const uint8_t max_ffe_level =
+			(link_settings->frl_link_rate > HDMI_FRL_LINK_RATE_12GBPS) ? 0x7 : 0x3;
 	struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
 	struct bp_transmitter_control cntl = { 0 };
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 39/41] drm/amd/display: Add FFE level defaults
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (35 preceding siblings ...)
  2026-07-31 21:12 ` [PATCH 38/41] drm/amd/display: switch max FFE level cap based on FRL link rate Roman.Li
@ 2026-07-31 21:13 ` Roman.Li
  2026-07-31 21:13 ` [PATCH 40/41] drm/amd/display: Migrate color manager HW and fix MCM blend LUT issues Roman.Li
                   ` (2 subsequent siblings)
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:13 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Relja Vojvodic,
	Nicholas Kazlauskas

From: Relja Vojvodic <Relja.Vojvodic@amd.com>

[How & Why]
Follow-up change to set defaults for HDMI FRL training

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Relja Vojvodic <Relja.Vojvodic@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c   | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c   | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c   | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c   | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c   | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c   | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c | 1 +
 drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c   | 1 +
 16 files changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
index f09bbb932150..dbb8bb7fc20d 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
@@ -753,6 +753,7 @@ static const struct dc_plane_cap plane_cap = {
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 3,
 	.disable_dmcu = true, //No DMCU on DCN30
 	.force_abm_enable = false,
 	.clock_trace = true,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
index d6b036e3933e..88dcf8166378 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
@@ -84,6 +84,7 @@
 #define DC_LOGGER_INIT(logger)
 
 static const struct dc_debug_options debug_defaults_drv = {
+		.limit_ffe = 3,
 		.disable_dmcu = true,
 		.force_abm_enable = false,
 		.clock_trace = true,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
index c8598ba23dd0..50b7c7b85fac 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
@@ -84,6 +84,7 @@
 
 
 static const struct dc_debug_options debug_defaults_drv = {
+		.limit_ffe = 3,
 		.disable_dmcu = true,
 		.force_abm_enable = false,
 		.clock_trace = true,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
index 8bb2b8b29cbf..db56e30cf259 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
@@ -915,6 +915,7 @@ static const struct dc_plane_cap plane_cap = {
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 3,
 	.disable_dmcu = true,
 	.force_abm_enable = false,
 	.clock_trace = true,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
index 5f08fb136b14..63f92e9da6d8 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
@@ -928,6 +928,7 @@ static const struct dc_plane_cap plane_cap = {
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 3,
 	.disable_z10 = false,
 	.enable_z9_disable_interface = true,
 	.minimum_z8_residency_time = 2100,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
index 470f3bd37314..15c1615c5f45 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
@@ -914,6 +914,7 @@ static const struct dc_plane_cap plane_cap = {
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 3,
 	.disable_z10 = true, /*hw not support it*/
 	.disable_dmcu = true,
 	.force_abm_enable = false,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
index d81d241901b4..a5ea35e45791 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
@@ -909,6 +909,7 @@ static const struct dc_plane_cap plane_cap = {
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 3,
 	.disable_z10 = true, /*hw not support it*/
 	.disable_dmcu = true,
 	.force_abm_enable = false,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
index a20ff9f0c3f8..7c2a79015f4e 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
@@ -745,6 +745,7 @@ static const struct dc_plane_cap plane_cap = {
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 3,
 	.disable_dmcu = true,
 	.force_abm_enable = false,
 	.clock_trace = true,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
index 105fba8ff171..5ee9a5a8ec3c 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
@@ -735,6 +735,7 @@ static const struct dc_plane_cap plane_cap = {
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 3,
 	.disable_dmcu = true,
 	.force_abm_enable = false,
 	.clock_trace = true,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
index a92e0dc5ad6a..52826e96c184 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
@@ -761,6 +761,7 @@ static const struct dc_plane_cap plane_cap = {
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 3,
 	.disable_dmcu = true,
 	.force_abm_enable = false,
 	.clock_trace = true,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
index 68a2169da0c1..e3fc71307c91 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
@@ -741,6 +741,7 @@ static const struct dc_plane_cap plane_cap = {
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 3,
 	.disable_dmcu = true,
 	.force_abm_enable = false,
 	.clock_trace = true,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
index ba04e8b9b569..c019a657005d 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c
@@ -748,6 +748,7 @@ static const struct dc_plane_cap plane_cap = {
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 3,
 	.disable_dmcu = true,
 	.force_abm_enable = false,
 	.clock_trace = true,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
index fff84f9ce816..aced8ff657bf 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
@@ -748,6 +748,7 @@ static const struct dc_plane_cap plane_cap = {
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 3,
 	.disable_dmcu = true,
 	.force_abm_enable = false,
 	.clock_trace = true,
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
index 7507994f12d8..6296330e2450 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
@@ -727,6 +727,7 @@ static const struct dc_plane_cap plane_cap = {
 	.min_height = 64};
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 3,
 	.disable_dmcu = true,
 	.force_abm_enable = false,
 	.clock_trace = true,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c
index 7b14d67314d5..41f0c67f57ff 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42b/dcn42b_resource.c
@@ -785,6 +785,7 @@ static const struct dc_plane_cap plane_cap = {
 	.min_height = 64};
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 3,
 	.disable_dmcu = true,
 	.force_abm_enable = false,
 	.clock_trace = true,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c
index 9dc6e4192943..b441d6d2d36b 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c
@@ -615,6 +615,7 @@ static const struct dc_plane_cap plane_cap = {
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
+	.limit_ffe = 7,
 	.disable_dmcu = true,
 	.force_abm_enable = false,
 	.clock_trace = true,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 40/41] drm/amd/display: Migrate color manager HW and fix MCM blend LUT issues
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (36 preceding siblings ...)
  2026-07-31 21:13 ` [PATCH 39/41] drm/amd/display: Add FFE level defaults Roman.Li
@ 2026-07-31 21:13 ` Roman.Li
  2026-07-31 21:13 ` [PATCH 41/41] drm/amd/display: Promote DC to 3.2.392 Roman.Li
  2026-08-04 13:24 ` [PATCH 00/41] DC Patches July 31, 2026 Wheeler, Daniel
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:13 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Rafal Ostrowski, Dillon Varone

From: Rafal Ostrowski <rafal.ostrowski@amd.com>

Combine two related color manager improvements:

1. Migrate MCM/RMCM, shaper and 3DLUT HW programming to dc_plane_cm
   - Continue convergence with upstream Color Manager refactor
   - Migrate MCM/RMCM, shaper and 3DLUT programming for dcn401+ to dc_plane_cm
   - Unify MCM programming across both legacy and 3DLUT DMA paths
   - Add 3DLUT DMA broadcast support for multi-pipe planes

2. Reprogram MCM blend LUT on blend_enable falling edge
   - Fix issue where SDR desktop remained desaturated after video playback
   - Detect blend_enable falling edge (1->0) in surface update detection
   - Force MCM LUT reprogramming on blend state change

Reviewed-by: Dillon Varone <dillon.varone@amd.com>
Signed-off-by: Rafal Ostrowski <rafal.ostrowski@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 drivers/gpu/drm/amd/display/dc/core/dc.c      |  66 +--
 .../drm/amd/display/dc/core/dc_hw_sequencer.c |  18 +
 .../gpu/drm/amd/display/dc/core/dc_stream.c   |   3 +-
 drivers/gpu/drm/amd/display/dc/dc.h           |  12 +-
 .../amd/display/dc/hubp/dcn401/dcn401_hubp.c  | 201 +++++---
 .../amd/display/dc/hubp/dcn401/dcn401_hubp.h  |  23 +-
 .../amd/display/dc/hubp/dcn42/dcn42_hubp.c    |  78 ++-
 .../amd/display/dc/hubp/dcn42/dcn42_hubp.h    |  10 +-
 .../amd/display/dc/hubp/dcn50/dcn50_hubp.c    |  10 +-
 .../amd/display/dc/hubp/dcn60/dcn60_hubp.c    |   7 +-
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 428 ++++++---------
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.h |   7 +-
 .../amd/display/dc/hwss/dcn401/dcn401_init.c  |   1 -
 .../amd/display/dc/hwss/dcn42/dcn42_hwseq.c   | 488 ++----------------
 .../amd/display/dc/hwss/dcn42/dcn42_hwseq.h   |   6 -
 .../amd/display/dc/hwss/dcn42/dcn42_init.c    |   2 -
 .../amd/display/dc/hwss/dcn60/dcn60_init.c    |   2 -
 .../drm/amd/display/dc/hwss/hw_sequencer.h    |   2 +-
 .../display/dc/hwss/hw_sequencer_private.h    |   5 -
 drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h  |  35 +-
 drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h   |  81 +--
 .../amd/display/dc/mpc/dcn401/dcn401_mpc.c    | 177 ++++---
 .../amd/display/dc/mpc/dcn401/dcn401_mpc.h    |  25 +-
 .../drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c  | 405 ++-------------
 .../drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h  |  55 +-
 .../drm/amd/display/dc/mpc/dcn60/dcn60_mpc.c  | 235 ++++-----
 .../drm/amd/display/dc/mpc/dcn60/dcn60_mpc.h  |  15 -
 .../dc/resource/dcn42/dcn42_resource.c        |   1 +
 .../dc/resource/dcn60/dcn60_resource.c        |   1 +
 29 files changed, 778 insertions(+), 1621 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 7f378b5e896c..68f228014305 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3027,13 +3027,14 @@ static struct dc_update_descriptor det_surface_update(
 		elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
 	}
 
-	if ((u->cm && u->cm->flags.bits.blend_enable) ||
+	if ((u->cm && (u->cm->flags.bits.blend_enable ||
+			u->cm->flags.bits.blend_enable != u->surface->cm.flags.bits.blend_enable)) ||
 			(u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) {
 		update_bits->gamma_change = 1;
 		elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
 	}
 
-	if (u->cm && (u->cm->flags.bits.lut3d_enable || u->cm->flags.bits.shaper_enable)) {
+	if (u->cm && (u->cm->flags.bits.lut3d_enable || u->surface->cm.flags.bits.lut3d_enable)) {
 		update_bits->lut_3d = 1;
 		elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
 	}
@@ -3075,25 +3076,12 @@ static struct dc_update_descriptor det_surface_update(
 			}
 		};
 
-		if (u->cm->flags.bits.shaper_enable != u->surface->cm.flags.bits.shaper_enable
-				|| u->cm->flags.bits.blend_enable != u->surface->cm.flags.bits.blend_enable
-				|| u->cm->flags.bits.lut3d_enable != u->surface->cm.flags.bits.lut3d_enable
-				|| u->cm->flags.bits.lut3d_dma_enable != u->surface->cm.flags.bits.lut3d_dma_enable) {
-			update_bits->mcm_transfer_function_enable_change = 1;
-			elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
-		}
-
 		if ((u->cm->flags.all != blend_only_flags.all && u->cm->flags.all != 0) ||
 				(u->surface->cm.flags.all != blend_only_flags.all && u->surface->cm.flags.all != 0)) {
 			elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
 		}
 	}
 
-	if (update_bits->lut_3d &&
-			!u->surface->cm.flags.bits.lut3d_dma_enable) {
-		elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
-	}
-
 	if (check_config->enable_legacy_fast_update &&
 			(update_bits->gamma_change ||
 			update_bits->gamut_remap_change ||
@@ -3446,46 +3434,6 @@ static void copy_surface_update_to_plane(
 		memcpy(&surface->cm, srf_update->cm, sizeof(surface->cm));
 		surface->cm.refcount = refcount;
 
-#ifndef TRIM_CM2
-		/* Populate mcm_luts from cm for legacy consumers (dml2, hwseq) */
-		surface->mcm_luts.lut1d_func = &surface->cm.blend_func;
-		surface->mcm_luts.shaper = &surface->cm.shaper_func;
-		if (srf_update->cm->flags.bits.lut3d_dma_enable) {
-			surface->mcm_luts.lut3d_data.lut3d_src = DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM;
-			surface->mcm_luts.lut3d_data.gpu_mem_params.addr = surface->cm.lut3d_dma.addr;
-			surface->mcm_luts.lut3d_data.gpu_mem_params.layout =
-				(surface->cm.lut3d_dma.swizzle == CM_LUT_3D_SWIZZLE_LINEAR_RGB) ?
-					DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB :
-				(surface->cm.lut3d_dma.swizzle == CM_LUT_3D_SWIZZLE_LINEAR_BGR) ?
-					DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR :
-					DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR;
-			surface->mcm_luts.lut3d_data.gpu_mem_params.format_params.format =
-				(surface->cm.lut3d_dma.format == CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB) ?
-					DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB :
-				(surface->cm.lut3d_dma.format == CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB) ?
-					DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB :
-					DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10;
-			surface->mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias =
-				surface->cm.lut3d_dma.bias;
-			surface->mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale =
-				surface->cm.lut3d_dma.scale;
-			surface->mcm_luts.lut3d_data.gpu_mem_params.component_order =
-				DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA;
-			surface->mcm_luts.lut3d_data.gpu_mem_params.size = DC_CM2_GPU_MEM_SIZE_TRANSFORMED;
-			surface->mcm_luts.lut3d_data.mpc_3dlut_enable = (srf_update->cm->flags.bits.lut3d_enable != 0);
-		} else {
-			surface->mcm_luts.lut3d_data.lut3d_src = DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM;
-			surface->mcm_luts.lut3d_data.lut3d_func = &surface->cm.lut3d_func;
-		}
-
-		if (srf_update->cm->flags.bits.shaper_enable &&
-				srf_update->cm->flags.bits.lut3d_enable)
-			surface->mcm_shaper_3dlut_setting = DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT;
-		else if (srf_update->cm->flags.bits.shaper_enable)
-			surface->mcm_shaper_3dlut_setting = DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER;
-		else
-			surface->mcm_shaper_3dlut_setting = DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL;
-#endif /* TRIM_CM2 */
 	}
 
 	if (srf_update->hdr_mult.value)
@@ -3496,12 +3444,6 @@ static void copy_surface_update_to_plane(
 		surface->sdr_white_level_nits =
 				srf_update->sdr_white_level_nits;
 
-	if (srf_update->cm &&
-			(srf_update->cm->flags.bits.blend_enable ||
-			srf_update->cm->flags.bits.shaper_enable ||
-			srf_update->cm->flags.bits.lut3d_enable))
-		surface->lut_bank_a = !surface->lut_bank_a;
-
 	if (srf_update->input_csc_color_matrix)
 		surface->input_csc_color_matrix =
 			*srf_update->input_csc_color_matrix;
@@ -5243,7 +5185,7 @@ static void commit_planes_for_stream(struct dc *dc,
 						srf_updates[i].cm->flags.bits.lut3d_enable &&
 						srf_updates[i].cm->flags.bits.lut3d_dma_enable &&
 						dc->hwss.trigger_3dlut_dma_load)
-					dc->hwss.trigger_3dlut_dma_load(dc, pipe_ctx);
+					dc->hwss.trigger_3dlut_dma_load(pipe_ctx);
 
 				/*program triple buffer after lock based on flip type*/
 				if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 8878652434d2..76e3509f73c5 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -1457,6 +1457,24 @@ void hwss_build_fast_sequence(struct dc *dc,
 					(*num_steps)++;
 				}
 
+				if (current_mpc_pipe->plane_state->update_bits.hdr_mult) {
+					struct fixed31_32 multiplier = current_mpc_pipe->plane_state->hdr_mult;
+					uint32_t hw_mult = 0x1f000; // 1.0 default multiplier
+					struct custom_float_format fmt;
+
+					fmt.exponenta_bits = 6;
+					fmt.mantissa_bits = 12;
+					fmt.sign = true;
+
+					if (!dc_fixpt_eq(multiplier, dc_fixpt_from_int(0)) && // check != 0
+						convert_to_custom_float_format(multiplier, &fmt, &hw_mult)) {
+						block_sequence[*num_steps].params.dpp_set_hdr_multiplier_params.dpp = current_mpc_pipe->plane_res.dpp;
+						block_sequence[*num_steps].params.dpp_set_hdr_multiplier_params.hw_mult = hw_mult;
+						block_sequence[*num_steps].func = DPP_SET_HDR_MULTIPLIER;
+						(*num_steps)++;
+					}
+				}
+
 				if (dc->hwss.program_gamut_remap &&
 						(current_mpc_pipe->plane_state->update_bits.gamut_remap_change ||
 						 current_mpc_pipe->stream->update_flags.bits.gamut_remap)) {
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index ce5b9e82db8d..9f3068e899e1 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -991,6 +991,7 @@ void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream)
 	}
 }
 
+/* TODO - move to per plane ownership? */
 /*
 *	dc_stream_get_3dlut()
 *	Requirements:
@@ -1042,7 +1043,6 @@ void dc_stream_release_3dlut_for_stream(
 	if (rmcm_3dlut) {
 		rmcm_3dlut->isInUse = false;
 		rmcm_3dlut->stream  = NULL;
-		rmcm_3dlut->protection_bits = 0;
 	}
 }
 
@@ -1054,7 +1054,6 @@ void dc_stream_init_rmcm_3dlut(struct dc *dc)
 	for (unsigned int i = 0; i < num_rmcm; i++) {
 		dc->res_pool->rmcm_3dlut[i].isInUse = false;
 		dc->res_pool->rmcm_3dlut[i].stream = NULL;
-		dc->res_pool->rmcm_3dlut[i].protection_bits = 0;
 	}
 }
 
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 683b5fb1945d..b2fd3a94f067 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1459,6 +1459,7 @@ struct dc_transfer_func {
 	enum dc_transfer_func_predefined tf;
 	/* FP16 1.0 reference level in nits, default is 80 nits, only for PQ*/
 	uint32_t sdr_ref_white_level;
+	struct fixed31_32 hdr_multiplier;
 	union {
 		struct pwl_params pwl;
 		struct dc_transfer_func_distributed_points tf_pts;
@@ -1509,13 +1510,11 @@ struct lut_mem_mapping {
 struct dc_rmcm_3dlut {
 	bool isInUse;
 	const struct dc_stream_state *stream;
-	uint8_t protection_bits;
 };
 
 struct dc_3dlut {
 	struct kref refcount;
 	struct tetrahedral_params lut_3d;
-	struct fixed31_32 hdr_multiplier;
 	union dc_3dlut_state state;
 };
 
@@ -1595,7 +1594,6 @@ struct pipe_update_bits {
 	uint32_t stereo_format_change:1;
 	uint32_t lut_3d:1;
 	uint32_t tmz_changed:1;
-	uint32_t mcm_transfer_function_enable_change:1; /* disable or enable MCM transfer func */
 	uint32_t full_update:1;
 	uint32_t sdr_white_level_nits:1;
 	uint32_t cm_hist_change:1;
@@ -1640,7 +1638,6 @@ static inline void dc_pipe_update_bits_set_full(struct pipe_update_bits *flags)
 	flags->stereo_format_change = 1;
 	flags->lut_3d = 1;
 	flags->tmz_changed = 1;
-	flags->mcm_transfer_function_enable_change = 1;
 	flags->full_update = 1;
 	flags->sdr_white_level_nits = 1;
 	flags->cm_hist_change = 1;
@@ -1674,7 +1671,6 @@ static inline bool dc_pipe_update_bits_is_any_set(const struct pipe_update_bits
 		flags->stereo_format_change ||
 		flags->lut_3d ||
 		flags->tmz_changed ||
-		flags->mcm_transfer_function_enable_change ||
 		flags->full_update ||
 		flags->sdr_white_level_nits ||
 		flags->cm_hist_change;
@@ -1709,18 +1705,16 @@ struct dc_plane_state {
 	enum dc_color_space color_space;
 
 #ifndef TRIM_CM2
-	// TODO: No longer used, remove
+	bool lut_bank_a;
 	struct dc_hdr_static_metadata hdr_static_ctx;
-
 	struct dc_3dlut lut3d_func;
 	struct dc_transfer_func in_shaper_func;
 	struct dc_transfer_func blend_tf;
 	enum dc_cm2_shaper_3dlut_setting mcm_shaper_3dlut_setting;
 	bool mcm_lut1d_enable;
 	struct dc_cm2_func_luts mcm_luts;
-#endif /* TRIM_CM2 */
-	bool lut_bank_a;
 	enum mpcc_movable_cm_location mcm_location;
+#endif /* TRIM_CM2 */
 	struct dc_plane_cm cm;
 
 	struct dc_transfer_func *gamcor_tf;
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
index 9965cf572354..a2e0bafb711a 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c
@@ -41,12 +41,12 @@
 	hubp2->hubp_shift->field_name, hubp2->hubp_mask->field_name
 
 void hubp401_program_3dlut_fl_addr(struct hubp *hubp,
-	const struct dc_plane_address address)
+	const struct dc_plane_address *address)
 {
 	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
 
-	REG_UPDATE(HUBP_3DLUT_ADDRESS_HIGH, HUBP_3DLUT_ADDRESS_HIGH, address.lut3d.addr.high_part);
-	REG_WRITE(HUBP_3DLUT_ADDRESS_LOW, address.lut3d.addr.low_part);
+	REG_UPDATE(HUBP_3DLUT_ADDRESS_HIGH, HUBP_3DLUT_ADDRESS_HIGH, address->lut3d.addr.high_part);
+	REG_WRITE(HUBP_3DLUT_ADDRESS_LOW, address->lut3d.addr.low_part);
 }
 
 void hubp401_program_3dlut_fl_dlg_param(struct hubp *hubp, int refcyc_per_3dlut_group)
@@ -72,33 +72,46 @@ uint32_t hubp401_get_3dlut_fl_done(struct hubp *hubp)
 	return ret;
 }
 
-void hubp401_program_3dlut_fl_addressing_mode(struct hubp *hubp, enum hubp_3dlut_fl_addressing_mode addr_mode)
+static void hubp401_get_3dlut_fl_xbar_map(
+		const enum dc_cm_lut_pixel_format format,
+		enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_y_g,
+		enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_cb_b,
+		enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_cr_r)
 {
-	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
-
-	REG_UPDATE(HUBP_3DLUT_CONTROL, HUBP_3DLUT_ADDRESSING_MODE, addr_mode);
-}
-
-void hubp401_program_3dlut_fl_width(struct hubp *hubp, enum hubp_3dlut_fl_width width)
-{
-	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
-
-	REG_UPDATE(HUBP_3DLUT_CONTROL, HUBP_3DLUT_WIDTH, width);
+	switch (format) {
+	case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12MSB:
+	case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12LSB:
+	case CM_LUT_PIXEL_FORMAT_BGRA16161616_FLOAT_FP1_5_10:
+		/* BGRA */
+		*bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47;
+		*bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
+		*bit_slice_cb_b =  hubp_3dlut_fl_crossbar_bit_slice_0_15;
+		break;
+	case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB:
+	case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB:
+	case CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10:
+	default:
+		/* RGBA */
+		*bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15;
+		*bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
+		*bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47;
+		break;
+	}
 }
 
-void hubp401_program_3dlut_fl_tmz_protected(struct hubp *hubp, uint8_t protection_bits)
+void hubp401_program_3dlut_fl_crossbar(struct hubp *hubp,
+		const enum dc_cm_lut_pixel_format format)
 {
 	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
 
-	REG_UPDATE(HUBP_3DLUT_CONTROL, HUBP_3DLUT_TMZ, protection_bits);
-}
+	enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_y_g = 0;
+	enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b = 0;
+	enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r = 0;
 
-void hubp401_program_3dlut_fl_crossbar(struct hubp *hubp,
-			enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_y_g,
-			enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b,
-			enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r)
-{
-	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+	hubp401_get_3dlut_fl_xbar_map(format,
+			&bit_slice_y_g,
+			&bit_slice_cb_b,
+			&bit_slice_cr_r);
 
 	REG_UPDATE_3(HUBP_3DLUT_CONTROL,
 			HUBP_3DLUT_CROSSBAR_SELECT_Y_G, bit_slice_y_g,
@@ -106,62 +119,122 @@ void hubp401_program_3dlut_fl_crossbar(struct hubp *hubp,
 			HUBP_3DLUT_CROSSBAR_SELECT_CR_R, bit_slice_cr_r);
 }
 
-void hubp401_update_3dlut_fl_bias_scale(struct hubp *hubp, uint16_t bias, uint16_t scale)
+static enum hubp_3dlut_fl_width hubp401_get_3dlut_fl_width(
+		const enum dc_cm_lut_size size,
+		const enum dc_cm_lut_swizzle swizzle)
 {
-	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+	enum hubp_3dlut_fl_width width = 0;
+
+	switch (size) {
+	case CM_LUT_SIZE_333333:
+		ASSERT(swizzle != CM_LUT_1D_PACKED_LINEAR);
+		width = hubp_3dlut_fl_width_33;
+		break;
+	case CM_LUT_SIZE_171717:
+		if (swizzle != CM_LUT_1D_PACKED_LINEAR) {
+			width = hubp_3dlut_fl_width_17;
+		} else {
+			width = hubp_3dlut_fl_width_17_transformed;
+		}
+		break;
+	default:
+		width = 0;
+		break;
+	}
 
-	REG_UPDATE_2(_3DLUT_FL_BIAS_SCALE, HUBP0_3DLUT_FL_BIAS, bias, HUBP0_3DLUT_FL_SCALE, scale);
+	return width;
 }
 
-void hubp401_program_3dlut_fl_mode(struct hubp *hubp, enum hubp_3dlut_fl_mode mode)
+static enum hubp_3dlut_fl_format hubp401_get_3dlut_fl_format(
+		const enum dc_cm_lut_pixel_format dc_format)
 {
-	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+	enum hubp_3dlut_fl_format hubp_format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
 
-	REG_UPDATE(_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_MODE, mode);
+	switch (dc_format) {
+	case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB:
+	case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12MSB:
+		hubp_format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
+		break;
+	case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB:
+	case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12LSB:
+		hubp_format = hubp_3dlut_fl_format_unorm_12lsb_bitslice;
+		break;
+	case CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10:
+	case CM_LUT_PIXEL_FORMAT_BGRA16161616_FLOAT_FP1_5_10:
+		hubp_format = hubp_3dlut_fl_format_float_fp1_5_10;
+		break;
+	default:
+		BREAK_TO_DEBUGGER();
+		break;
+	}
+
+	return hubp_format;
 }
 
-void hubp401_program_3dlut_fl_format(struct hubp *hubp, enum hubp_3dlut_fl_format format)
+static enum hubp_3dlut_fl_addressing_mode hubp401_get_3dlut_fl_addr_mode(
+		const enum dc_cm_lut_swizzle swizzle)
 {
-	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+	enum hubp_3dlut_fl_addressing_mode addr_mode;
+
+	switch (swizzle) {
+	case CM_LUT_1D_PACKED_LINEAR:
+		addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear;
+		break;
+	case CM_LUT_3D_SWIZZLE_LINEAR_RGB:
+	case CM_LUT_3D_SWIZZLE_LINEAR_BGR:
+	default:
+		addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
+		break;
+	}
 
-	REG_UPDATE(_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_FORMAT, format);
+	return addr_mode;
 }
 
-void hubp401_program_3dlut_fl_config(
-	struct hubp *hubp,
-	struct hubp_fl_3dlut_config *cfg)
+static enum hubp_3dlut_fl_mode hubp401_get_3dlut_fl_mode(
+		const enum dc_cm_lut_swizzle swizzle)
 {
-	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+	enum hubp_3dlut_fl_mode mode;
 
-	uint32_t mpc_width = {(cfg->width == 17) ? 0 : 1};
-	uint32_t width = {cfg->width};
+	switch (swizzle) {
+	case CM_LUT_3D_SWIZZLE_LINEAR_RGB:
+		mode = hubp_3dlut_fl_mode_native_1;
+		break;
+	case CM_LUT_3D_SWIZZLE_LINEAR_BGR:
+		mode = hubp_3dlut_fl_mode_native_2;
+		break;
+	case CM_LUT_1D_PACKED_LINEAR:
+		mode = hubp_3dlut_fl_mode_transform;
+		break;
+	default:
+		mode = hubp_3dlut_fl_mode_disable;
+		break;
+	}
 
-	if (cfg->layout == CM_LUT_1D_PACKED_LINEAR)
-		width = (cfg->width == 17) ? 4916 : 35940;
+	return mode;
+}
+
+void hubp401_program_3dlut_fl_config(struct hubp *hubp,
+		const struct dc_3dlut_dma *config)
+{
+	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+	enum hubp_3dlut_fl_width width = hubp401_get_3dlut_fl_width(config->size, config->swizzle);
+	enum hubp_3dlut_fl_format format = hubp401_get_3dlut_fl_format(config->format);
+	enum hubp_3dlut_fl_addressing_mode addr_mode = hubp401_get_3dlut_fl_addr_mode(config->swizzle);
+	enum hubp_3dlut_fl_mode mode = hubp401_get_3dlut_fl_mode(config->swizzle);
 
 	REG_UPDATE_2(_3DLUT_FL_CONFIG,
-		HUBP0_3DLUT_FL_MODE, cfg->mode,
-		HUBP0_3DLUT_FL_FORMAT, cfg->format);
+			HUBP0_3DLUT_FL_MODE, mode,
+			HUBP0_3DLUT_FL_FORMAT, format);
 
 	REG_UPDATE_2(_3DLUT_FL_BIAS_SCALE,
-		HUBP0_3DLUT_FL_BIAS, cfg->bias,
-		HUBP0_3DLUT_FL_SCALE, cfg->scale);
-
-	REG_UPDATE(HUBP_3DLUT_ADDRESS_HIGH,
-		HUBP_3DLUT_ADDRESS_HIGH, cfg->address.lut3d.addr.high_part);
-	REG_UPDATE(HUBP_3DLUT_ADDRESS_LOW,
-		HUBP_3DLUT_ADDRESS_LOW, cfg->address.lut3d.addr.low_part);
-
-	//cross bar
-	REG_UPDATE_8(HUBP_3DLUT_CONTROL,
-		HUBP_3DLUT_MPC_WIDTH, mpc_width,
-		HUBP_3DLUT_WIDTH, width,
-		HUBP_3DLUT_CROSSBAR_SELECT_CR_R, cfg->crossbar_bit_slice_cr_r,
-		HUBP_3DLUT_CROSSBAR_SELECT_Y_G, cfg->crossbar_bit_slice_y_g,
-		HUBP_3DLUT_CROSSBAR_SELECT_CB_B, cfg->crossbar_bit_slice_cb_b,
-		HUBP_3DLUT_ADDRESSING_MODE, cfg->addr_mode,
-		HUBP_3DLUT_TMZ, cfg->protection_bits,
-		HUBP_3DLUT_ENABLE, cfg->enabled ? 1 : 0);
+			HUBP0_3DLUT_FL_BIAS, config->bias,
+			HUBP0_3DLUT_FL_SCALE, config->scale);
+
+	REG_UPDATE_3(HUBP_3DLUT_CONTROL,
+			HUBP_3DLUT_WIDTH, width,
+			HUBP_3DLUT_ADDRESSING_MODE, addr_mode,
+			HUBP_3DLUT_TMZ, config->addr.tmz_surface);
 }
 
 void hubp401_update_mall_sel(struct hubp *hubp, uint32_t mall_sel, bool c_cursor)
@@ -1062,19 +1135,13 @@ static struct hubp_funcs dcn401_hubp_funcs = {
 	.hubp_update_mall_sel = hubp401_update_mall_sel,
 	.hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering,
 	.hubp_program_mcache_id_and_split_coordinate = hubp401_program_mcache_id_and_split_coordinate,
-	.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_config = hubp401_program_3dlut_fl_config,
 	.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 = hubp401_program_3dlut_fl_crossbar,
 	.hubp_get_3dlut_fl_done = hubp401_get_3dlut_fl_done,
 	.hubp_clear_tiling = hubp401_clear_tiling,
-	.hubp_program_3dlut_fl_config = hubp401_program_3dlut_fl_config,
 	.hubp_read_reg_state = hubp3_read_reg_state
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h
index 4116834c552d..adf343837652 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h
@@ -328,32 +328,17 @@ uint32_t hubp401_get_3dlut_fl_done(struct hubp *hubp);
 
 void hubp401_set_unbounded_requesting(struct hubp *hubp, bool enable);
 
-void hubp401_update_3dlut_fl_bias_scale(struct hubp *hubp, uint16_t bias, uint16_t scale);
-
 void hubp401_program_3dlut_fl_crossbar(struct hubp *hubp,
-	enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_y_g,
-	enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b,
-	enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r);
-
-void hubp401_program_3dlut_fl_tmz_protected(struct hubp *hubp, uint8_t protection_bits);
-
-void hubp401_program_3dlut_fl_width(struct hubp *hubp, enum hubp_3dlut_fl_width width);
-
-void hubp401_program_3dlut_fl_addressing_mode(struct hubp *hubp, enum hubp_3dlut_fl_addressing_mode addr_mode);
+		const enum dc_cm_lut_pixel_format format);
 
 void hubp401_enable_3dlut_fl(struct hubp *hubp, bool enable);
 
 void hubp401_program_3dlut_fl_dlg_param(struct hubp *hubp, int refcyc_per_3dlut_group);
 
-void hubp401_program_3dlut_fl_addr(struct hubp *hubp, const struct dc_plane_address address);
+void hubp401_program_3dlut_fl_addr(struct hubp *hubp, const struct dc_plane_address *address);
 
-void hubp401_program_3dlut_fl_format(struct hubp *hubp, enum hubp_3dlut_fl_format format);
-
-void hubp401_program_3dlut_fl_mode(struct hubp *hubp, enum hubp_3dlut_fl_mode mode);
-
-void hubp401_program_3dlut_fl_config(
-	struct hubp *hubp,
-	struct hubp_fl_3dlut_config *cfg);
+void hubp401_program_3dlut_fl_config(struct hubp *hubp,
+		const struct dc_3dlut_dma *config);
 
 void hubp401_clear_tiling(struct hubp *hubp);
 
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
index 94730f3cff42..86e49eb84a54 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c
@@ -317,19 +317,84 @@ static void hubp42_program_surface_config(
 	hubp42_program_pixel_format(hubp, format);
 }
 
+static void hubp42_get_3dlut_fl_xbar_map(
+		const enum dc_cm_lut_pixel_format format,
+		enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_y_g,
+		enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_cb_b,
+		enum hubp_3dlut_fl_crossbar_bit_slice *bit_slice_cr_r)
+{
+	switch (format) {
+	case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12MSB:
+	case CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12LSB:
+	case CM_LUT_PIXEL_FORMAT_BGRA16161616_FLOAT_FP1_5_10:
+		/* BGRA */
+		*bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_32_47;
+		*bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
+		*bit_slice_cb_b =  hubp_3dlut_fl_crossbar_bit_slice_0_15;
+		break;
+	case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB:
+	case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB:
+	case CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10:
+	default:
+		/* RGBA */
+		*bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15;
+		*bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
+		*bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47;
+		break;
+	}
+}
+
 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)
+		const enum dc_cm_lut_pixel_format format)
 {
 	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
 
+	enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_g = 0;
+	enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_b = 0;
+	enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_r = 0;
+
+	hubp42_get_3dlut_fl_xbar_map(format,
+			&bit_slice_g,
+			&bit_slice_b,
+			&bit_slice_r);
+
 	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 uint32_t hubp42_get_3dlut_fl_mpc_width(
+		const enum dc_cm_lut_size size)
+{
+	uint32_t width = 0;
+
+	switch (size) {
+	case CM_LUT_SIZE_333333:
+		width = 1;
+		break;
+	case CM_LUT_SIZE_171717:
+	default:
+		width = 0;
+		break;
+	}
+
+	return width;
+}
+
+void hubp42_program_3dlut_fl_config(struct hubp *hubp,
+		const struct dc_3dlut_dma *config)
+{
+	struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+	uint32_t mpc_width = hubp42_get_3dlut_fl_mpc_width(config->size);
+
+	REG_UPDATE(HUBP_3DLUT_CONTROL,
+			HUBP_3DLUT_MPC_WIDTH, mpc_width);
+
+	hubp401_program_3dlut_fl_config(hubp, config);
+}
+
 static bool hubp42_program_surface_flip_and_addr(
 	struct hubp *hubp,
 	const struct dc_plane_address *address,
@@ -660,15 +725,10 @@ struct hubp_funcs dcn42_hubp_funcs = {
 	.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_config = hubp42_program_3dlut_fl_config,
 	.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_clear_tiling = hubp3_clear_tiling,
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
index ba4a58c353dd..3a030e5e517e 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h
@@ -79,11 +79,11 @@ bool hubp42_construct(
 	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_program_3dlut_fl_crossbar(struct hubp *hubp,
+		const enum dc_cm_lut_pixel_format format);
+
+void hubp42_program_3dlut_fl_config(struct hubp *hubp,
+		const struct dc_3dlut_dma *config);
 
 void hubp42_read_state(struct hubp *hubp);
 
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn50/dcn50_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn50/dcn50_hubp.c
index e704ce5cd0a0..0230f03590cf 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn50/dcn50_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn50/dcn50_hubp.c
@@ -7,6 +7,7 @@
 #include "reg_helper.h"
 #include "basics/conversion.h"
 #include "dcn50_hubp.h"
+#include "dcn42/dcn42_hubp.h"
 
 #define REG(reg)\
 	hubp2->hubp_regs->reg
@@ -500,16 +501,11 @@ static struct hubp_funcs dcn50_hubp_funcs = {
 	.hubp_update_mall_sel = hubp401_update_mall_sel,
 	.hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering,
 	.hubp_program_mcache_id_and_split_coordinate = hubp401_program_mcache_id_and_split_coordinate,
-	.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_config = hubp42_program_3dlut_fl_config,
 	.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 = hubp401_program_3dlut_fl_crossbar,
+	.hubp_program_3dlut_fl_crossbar = hubp42_program_3dlut_fl_crossbar,
 	.hubp_get_3dlut_fl_done = hubp401_get_3dlut_fl_done,
 	.hubp_clear_tiling = hubp401_clear_tiling,
 	.hubp_read_reg_state = hubp3_read_reg_state
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.c
index 1065303f1d72..d22fe26aae62 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.c
@@ -441,15 +441,10 @@ static struct hubp_funcs dcn60_hubp_funcs = {
 	.hubp_update_mall_sel = NULL,
 	.hubp_prepare_subvp_buffering = hubp32_prepare_subvp_buffering,
 	.hubp_program_mcache_id_and_split_coordinate = hubp401_program_mcache_id_and_split_coordinate,
-	.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_config = hubp42_program_3dlut_fl_config,
 	.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_clear_tiling = hubp401_clear_tiling,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index 904780e02f70..51596f445a09 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -99,10 +99,6 @@ void dcn401_program_gamut_remap(struct program_gamut_remap_params *params)
 	unsigned int i = 0;
 	struct mpc_grph_gamut_adjustment mpc_adjust;
 
-	//For now assert if location is not pre-blend
-	if (plane)
-		ASSERT(plane->mcm_location == MPCC_MOVABLE_CM_LOCATION_BEFORE);
-
 	// program MPCC_MCM_FIRST_GAMUT_REMAP
 	memset(&mpc_adjust, 0, sizeof(mpc_adjust));
 	mpc_adjust.gamut_adjust_type = GRAPHICS_GAMUT_ADJUST_TYPE_BYPASS;
@@ -413,289 +409,200 @@ void dcn401_init_hw(struct dc *dc)
 	}
 }
 
-static void dcn401_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)
+void dcn401_trigger_3dlut_dma_load(struct pipe_ctx *pipe_ctx)
 {
-	struct mpc *mpc = dc->res_pool->mpc;
-	int mpcc_id = pipe_ctx->plane_res.hubp->inst;
-
-	if (!pipe_ctx->plane_state)
-		return;
+	const struct pipe_ctx *primary_dpp_pipe_ctx = resource_get_primary_dpp_pipe(pipe_ctx);
+	struct hubp *primary_hubp = primary_dpp_pipe_ctx ?
+			primary_dpp_pipe_ctx->plane_res.hubp : NULL;
 
-	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 = pipe_ctx->plane_state->cm.flags.bits.blend_enable ?
-		MCM_LUT_ENABLE : MCM_LUT_DISABLE;
-	*shaper_xable = pipe_ctx->plane_state->cm.flags.bits.shaper_enable ?
-		MCM_LUT_ENABLE : MCM_LUT_DISABLE;
-	*lut3d_xable = (pipe_ctx->plane_state->cm.flags.bits.shaper_enable &&
-			pipe_ctx->plane_state->cm.flags.bits.lut3d_enable) ?
-		MCM_LUT_ENABLE : MCM_LUT_DISABLE;
+	if (primary_hubp && primary_hubp->funcs->hubp_enable_3dlut_fl) {
+		primary_hubp->funcs->hubp_enable_3dlut_fl(primary_hubp, true);
+	}
 }
 
-void dcn401_populate_mcm_luts(struct dc *dc,
-		struct pipe_ctx *pipe_ctx,
-		const struct dc_plane_cm *cm,
-		bool lut_bank_a)
+bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx,
+				const struct dc_plane_state *plane_state)
 {
+	struct dc *dc = pipe_ctx->plane_res.hubp->ctx->dc;
+	const struct pipe_ctx *primary_dpp_pipe_ctx = resource_get_primary_dpp_pipe(pipe_ctx);
 	struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
 	struct hubp *hubp = pipe_ctx->plane_res.hubp;
+	struct hubp *primary_hubp = primary_dpp_pipe_ctx ?
+			primary_dpp_pipe_ctx->plane_res.hubp : hubp;   /* fall back to current pipe */
+	const struct dc_plane_cm *cm = &plane_state->cm;
 	int mpcc_id = hubp->inst;
 	struct mpc *mpc = dc->res_pool->mpc;
 	union mcm_lut_params m_lut_params;
-	const bool lut3d_dma = !!cm->flags.bits.lut3d_dma_enable;
-	enum hubp_3dlut_fl_format format = 0;
-	enum hubp_3dlut_fl_mode mode;
-	/* Width was previously hard-coded to TRANSFORMED via local_mcm build,
-	 * preserve identical behavior.
-	 */
-	enum hubp_3dlut_fl_width width = hubp_3dlut_fl_width_transformed;
-	enum hubp_3dlut_fl_addressing_mode addr_mode;
-	enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g;
-	enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b;
-	enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r;
-	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;
+	struct dc_3dlut_dma lut3d_dma;
+	bool lut_enable;
+	bool lut_bank_a;
 	bool rval;
+	bool result = true;
+
+	/* decide LUT bank based on current in use */
+	mpc->funcs->get_lut_mode(mpc, MCM_LUT_1DLUT, mpcc_id, &lut_enable, &lut_bank_a);
+	if (!lut_enable) {
+		mpc->funcs->get_lut_mode(mpc, MCM_LUT_SHAPER, mpcc_id, &lut_enable, &lut_bank_a);
+	}
+	if (!lut_enable) {
+		mpc->funcs->get_lut_mode(mpc, MCM_LUT_3DLUT, mpcc_id, &lut_enable, &lut_bank_a);
+	}
 
-	dcn401_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable);
+	/* switch to the next bank */
+	if (lut_enable) {
+		lut_bank_a = !lut_bank_a;
+	}
+
+	/* MCM location fixed to pre-blend */
+	mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id);
 
 	/* 1D LUT */
-	{
-		memset(&m_lut_params, 0, sizeof(m_lut_params));
+	lut_enable = cm->flags.bits.blend_enable != 0u;
+	memset(&m_lut_params, 0, sizeof(m_lut_params));
+	if (lut_enable) {
 		if (cm->blend_func.type == TF_TYPE_HWPWL)
 			m_lut_params.pwl = &cm->blend_func.pwl;
 		else if (cm->blend_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
-			rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx,
+			rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
 					&cm->blend_func,
-					&dpp_base->regamma_params, false);
+					&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 (!m_lut_params.pwl) {
+			lut_enable = false;
 		}
-		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);
+	} else {
+		lut_enable = false;
 	}
 
+	if (mpc->funcs->program_lut_mode)
+		mpc->funcs->program_lut_mode(mpc, MCM_LUT_1DLUT, lut_enable, lut_bank_a, CM_LUT_SIZE_NONE, mpcc_id);
+	if (lut_enable && mpc->funcs->populate_lut)
+		mpc->funcs->populate_lut(mpc, MCM_LUT_1DLUT, &m_lut_params, lut_bank_a, mpcc_id);
+
 	/* Shaper */
-	if (cm->flags.bits.lut3d_enable) {
+	lut_enable = cm->flags.bits.shaper_enable != 0u;
+	if (lut_enable) {
 		memset(&m_lut_params, 0, sizeof(m_lut_params));
 		if (cm->shaper_func.type == TF_TYPE_HWPWL)
 			m_lut_params.pwl = &cm->shaper_func.pwl;
 		else if (cm->shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
 			ASSERT(false);
-			rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx,
+			rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
 					&cm->shaper_func,
-					&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);
+					&dpp_base->shaper_params,
+					true);
+			m_lut_params.pwl = rval ? &dpp_base->shaper_params : NULL;
 		}
-	}
-
-	/* 3DLUT */
-	if (!lut3d_dma) {
-		/* SYSMEM (legacy lut3d_func) */
-		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 (cm->lut3d_func.state.bits.initialized) {
-			m_lut_params.lut3d = &cm->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);
+		if (!m_lut_params.pwl) {
+			lut_enable = false;
 		}
 	} else {
-		/* VIDMEM (3DLUT DMA Fast Load) */
+		lut_enable = false;
+	}
 
-		/* Select width based on the requested LUT size */
-		switch (cm->lut3d_dma.size) {
-		case CM_LUT_SIZE_333333:
-			if (dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_33)
-				width = hubp_3dlut_fl_width_33;
-			break;
-		case CM_LUT_SIZE_171717:
-			width = hubp_3dlut_fl_width_17;
-			break;
-		default:
-			/* keep default hubp_3dlut_fl_width_transformed */
-			break;
-		}
+	if (mpc->funcs->program_lut_mode)
+		mpc->funcs->program_lut_mode(mpc, MCM_LUT_SHAPER, lut_enable, lut_bank_a, CM_LUT_SIZE_NONE, mpcc_id);
+	if (lut_enable && mpc->funcs->populate_lut)
+		mpc->funcs->populate_lut(mpc, MCM_LUT_SHAPER, &m_lut_params, lut_bank_a, mpcc_id);
 
-		//check for support
-		if (mpc->funcs->mcm.is_config_supported &&
-			!mpc->funcs->mcm.is_config_supported(width))
-			return;
+	/* NOTE: Toggling from DMA->Host is not supported atomically as hardware
+	 * blocks writes until 3DLUT FL mode is cleared from HUBP on VUpdate.
+	 * Expectation is either option is used consistently.
+	*/
 
-		if (mpc->funcs->program_lut_read_write_control)
-			mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, mpcc_id);
+	/* 3DLUT */
+	lut_enable = cm->flags.bits.lut3d_enable != 0u;
+	if (lut_enable && cm->flags.bits.lut3d_dma_enable) {
+		/* Fast (DMA) Load Mode */
+		/* MPC */
 		if (mpc->funcs->program_lut_mode)
-			mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a, mpcc_id);
+			mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut_enable, lut_bank_a, cm->lut3d_dma.size, mpcc_id);
 
-		if (hubp->funcs->hubp_program_3dlut_fl_addr)
-			hubp->funcs->hubp_program_3dlut_fl_addr(hubp, cm->lut3d_dma.addr);
-
-		/* bit_depth was previously zero-initialized in local_mcm,
-		 * preserve identical behavior.
-		 */
-		if (mpc->funcs->mcm.program_bit_depth)
-			mpc->funcs->mcm.program_bit_depth(mpc, 0, mpcc_id);
-
-		switch (cm->lut3d_dma.swizzle) {
-		case CM_LUT_3D_SWIZZLE_LINEAR_RGB:
-			mode = hubp_3dlut_fl_mode_native_1;
-			addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
-			break;
-		case CM_LUT_3D_SWIZZLE_LINEAR_BGR:
-			mode = hubp_3dlut_fl_mode_native_2;
-			addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
-			break;
-		case CM_LUT_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;
-		}
-		if (hubp->funcs->hubp_program_3dlut_fl_mode)
-			hubp->funcs->hubp_program_3dlut_fl_mode(hubp, mode);
+		/* only supports 12 bit */
+		if (mpc->funcs->program_lut_read_write_control)
+			mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, 12, mpcc_id);
 
-		if (hubp->funcs->hubp_program_3dlut_fl_addressing_mode)
-			hubp->funcs->hubp_program_3dlut_fl_addressing_mode(hubp, addr_mode);
+		if (mpc->funcs->update_3dlut_fast_load_select)
+			mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, primary_hubp->inst);
 
-		switch (cm->lut3d_dma.format) {
-		case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB:
-			format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
-			break;
-		case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB:
-			format = hubp_3dlut_fl_format_unorm_12lsb_bitslice;
-			break;
-		case CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10:
-			format = hubp_3dlut_fl_format_float_fp1_5_10;
-			break;
-		default:
-			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,
-				cm->lut3d_dma.bias,
-				cm->lut3d_dma.scale,
-				mpcc_id);
-			hubp->funcs->hubp_update_3dlut_fl_bias_scale(hubp,
-				cm->lut3d_dma.bias,
-				cm->lut3d_dma.scale);
-		}
+		/* HUBP */
+		if (primary_hubp->inst == hubp->inst) {
+			/* only program if this is the primary dpp pipe for the given plane */
+			if (hubp->funcs->hubp_program_3dlut_fl_config)
+				hubp->funcs->hubp_program_3dlut_fl_config(hubp, &cm->lut3d_dma);
 
-		/* component_order was previously hard-coded to RGBA in local_mcm,
-		 * preserve identical behavior.
-		 */
-		crossbar_bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15;
-		crossbar_bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
-		crossbar_bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47;
+			if (hubp->funcs->hubp_program_3dlut_fl_crossbar)
+				hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp, cm->lut3d_dma.format);
 
-		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 (hubp->funcs->hubp_program_3dlut_fl_addr)
+				hubp->funcs->hubp_program_3dlut_fl_addr(hubp, &cm->lut3d_dma.addr);
 
-		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 (hubp->funcs->hubp_enable_3dlut_fl) {
+				hubp->funcs->hubp_enable_3dlut_fl(hubp, true);
+			} else {
+				/* GPU memory only supports fast load path */
+				BREAK_TO_DEBUGGER();
+				lut_enable = false;
+				result = false;
+			}
+		} else {
+			/* re-trigger primary HUBP to load 3DLUT */
+			if (primary_hubp->funcs->hubp_enable_3dlut_fl) {
+				primary_hubp->funcs->hubp_enable_3dlut_fl(primary_hubp, true);
+			}
 
-		if (mpc->funcs->mcm.program_3dlut_size)
-			mpc->funcs->mcm.program_3dlut_size(mpc, width, mpcc_id);
+			/* clear FL setup on this pipe's HUBP */
+			memset(&lut3d_dma, 0, sizeof(lut3d_dma));
+			if (hubp->funcs->hubp_program_3dlut_fl_config)
+				hubp->funcs->hubp_program_3dlut_fl_config(hubp, &lut3d_dma);
 
-		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, false);
+		}
+	} else {
+		/* Legacy (Host) Load Mode */
+		memset(&m_lut_params, 0, sizeof(m_lut_params));
 
-		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);
-			}
+		if (cm->flags.bits.lut3d_enable && cm->lut3d_func.state.bits.initialized) {
+			m_lut_params.lut3d = &cm->lut3d_func.lut_3d;
+		} else {
+			lut_enable = false;
 		}
-	}
-}
 
-void dcn401_trigger_3dlut_dma_load(struct dc *dc, struct pipe_ctx *pipe_ctx)
-{
-	(void)dc;
-	struct hubp *hubp = pipe_ctx->plane_res.hubp;
+		/* MPC */
+		if (mpc->funcs->program_lut_mode)
+			mpc->funcs->program_lut_mode(mpc,
+					MCM_LUT_3DLUT,
+					lut_enable,
+					lut_bank_a,
+					cm->lut3d_func.lut_3d.use_tetrahedral_9 ? CM_LUT_SIZE_999 : CM_LUT_SIZE_171717,
+					mpcc_id);
+
+		if (lut_enable) {
+			if (mpc->funcs->program_lut_read_write_control)
+				mpc->funcs->program_lut_read_write_control(mpc,
+						MCM_LUT_3DLUT,
+						lut_bank_a,
+						cm->lut3d_func.lut_3d.use_12bits ? 12 : 10,
+						mpcc_id);
 
-	if (hubp->funcs->hubp_enable_3dlut_fl) {
-		hubp->funcs->hubp_enable_3dlut_fl(hubp, true);
-	}
-}
+			if (mpc->funcs->update_3dlut_fast_load_select)
+				mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, 0xf);
 
-bool dcn401_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 (mpc->funcs->populate_lut)
+				mpc->funcs->populate_lut(mpc, MCM_LUT_3DLUT, &m_lut_params, lut_bank_a, mpcc_id);
+		}
 
-	if (plane_state->cm.flags.bits.lut3d_dma_enable) {
-		dcn401_populate_mcm_luts(dc, pipe_ctx, &plane_state->cm, plane_state->lut_bank_a);
-		return true;
-	}
+		/* HUBP */
+		memset(&lut3d_dma, 0, sizeof(lut3d_dma));
+		if (hubp->funcs->hubp_program_3dlut_fl_config)
+			hubp->funcs->hubp_program_3dlut_fl_config(hubp, &lut3d_dma);
 
-	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->cm.blend_func.type == TF_TYPE_HWPWL)
-		lut_params = &plane_state->cm.blend_func.pwl;
-	else if (plane_state->cm.blend_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
-		rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
-							       &plane_state->cm.blend_func,
-							       &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->cm.shaper_func.type == TF_TYPE_HWPWL)
-		lut_params = &plane_state->cm.shaper_func.pwl;
-	else if (plane_state->cm.shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
-		// TODO: dpp_base replace
-		rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
-							       &plane_state->cm.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->cm.lut3d_func.state.bits.initialized == 1)
-			result &= mpc->funcs->program_3dlut(mpc, &plane_state->cm.lut3d_func.lut_3d, mpcc_id);
-		else
-			result &= mpc->funcs->program_3dlut(mpc, NULL, mpcc_id);
+		if (hubp->funcs->hubp_enable_3dlut_fl)
+			hubp->funcs->hubp_enable_3dlut_fl(hubp, false);
 	}
 
 	return result;
@@ -2096,42 +2003,41 @@ void dcn401_perform_3dlut_wa_unlock(struct pipe_ctx *pipe_ctx)
 	if (!pipe_ctx)
 		return;
 
-	struct pipe_ctx *wa_pipes[MAX_PIPES] = { NULL };
-	struct pipe_ctx *odm_pipe, *mpc_pipe;
-	int i, wa_pipe_ct = 0;
+	const struct pipe_ctx *otg_master_pipe_ctx = resource_get_otg_master(pipe_ctx);
+	struct timing_generator *tg = otg_master_pipe_ctx ?
+			otg_master_pipe_ctx->stream_res.tg : NULL;
+	const struct pipe_ctx *primary_dpp_pipe_ctx = resource_is_pipe_type(pipe_ctx, DPP_PIPE) ?
+			resource_get_primary_dpp_pipe(pipe_ctx) : pipe_ctx;
+	struct hubp *primary_hubp = primary_dpp_pipe_ctx ?
+			primary_dpp_pipe_ctx->plane_res.hubp : NULL;
 
-	for (odm_pipe = pipe_ctx; odm_pipe != NULL; odm_pipe = odm_pipe->next_odm_pipe) {
-		for (mpc_pipe = odm_pipe; mpc_pipe != NULL; mpc_pipe = mpc_pipe->bottom_pipe) {
-			if (mpc_pipe->plane_state &&
-					mpc_pipe->plane_state->cm.flags.bits.lut3d_enable &&
-					mpc_pipe->plane_state->cm.flags.bits.lut3d_dma_enable) {
-				wa_pipes[wa_pipe_ct++] = mpc_pipe;
-			}
-		}
+	if (!otg_master_pipe_ctx || !tg) {
+		return;
 	}
 
-	if (wa_pipe_ct > 0) {
-		if (pipe_ctx->stream_res.tg->funcs->set_vupdate_keepout)
-			pipe_ctx->stream_res.tg->funcs->set_vupdate_keepout(pipe_ctx->stream_res.tg, true);
+	if (primary_dpp_pipe_ctx &&
+			primary_dpp_pipe_ctx->plane_state &&
+			primary_dpp_pipe_ctx->plane_state->cm.flags.bits.lut3d_enable &&
+			primary_dpp_pipe_ctx->plane_state->cm.flags.bits.lut3d_dma_enable) {
+		if (tg->funcs->set_vupdate_keepout)
+			tg->funcs->set_vupdate_keepout(tg, true);
 
-		for (i = 0; i < wa_pipe_ct; ++i) {
-			if (wa_pipes[i]->plane_res.hubp->funcs->hubp_enable_3dlut_fl)
-				wa_pipes[i]->plane_res.hubp->funcs->hubp_enable_3dlut_fl(wa_pipes[i]->plane_res.hubp, true);
+		if (primary_hubp && primary_hubp->funcs->hubp_enable_3dlut_fl) {
+			primary_hubp->funcs->hubp_enable_3dlut_fl(primary_hubp, true);
 		}
 
-		pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
-		if (pipe_ctx->stream_res.tg->funcs->wait_update_lock_status)
-			pipe_ctx->stream_res.tg->funcs->wait_update_lock_status(pipe_ctx->stream_res.tg, false);
+		tg->funcs->unlock(tg);
+		if (tg->funcs->wait_update_lock_status)
+			tg->funcs->wait_update_lock_status(tg, false);
 
-		for (i = 0; i < wa_pipe_ct; ++i) {
-			if (wa_pipes[i]->plane_res.hubp->funcs->hubp_enable_3dlut_fl)
-				wa_pipes[i]->plane_res.hubp->funcs->hubp_enable_3dlut_fl(wa_pipes[i]->plane_res.hubp, true);
+		if (primary_hubp && primary_hubp->funcs->hubp_enable_3dlut_fl) {
+			primary_hubp->funcs->hubp_enable_3dlut_fl(primary_hubp, true);
 		}
 
-		if (pipe_ctx->stream_res.tg->funcs->set_vupdate_keepout)
-			pipe_ctx->stream_res.tg->funcs->set_vupdate_keepout(pipe_ctx->stream_res.tg, false);
+		if (tg->funcs->set_vupdate_keepout)
+			tg->funcs->set_vupdate_keepout(tg, false);
 	} else {
-		pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
+		tg->funcs->unlock(tg);
 	}
 }
 
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
index f90e25243ead..69c7dc73a29a 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.h
@@ -39,8 +39,7 @@ void dcn401_init_hw(struct dc *dc);
 bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx,
 				const struct dc_plane_state *plane_state);
 bool dcn401_set_output_transfer_func(struct set_output_transfer_func_params *params);
-void dcn401_trigger_3dlut_dma_load(struct dc *dc,
-				struct pipe_ctx *pipe_ctx);
+void dcn401_trigger_3dlut_dma_load(struct pipe_ctx *pipe_ctx);
 void dcn401_calculate_dccg_tmds_div_value(struct pipe_ctx *pipe_ctx,
 				unsigned int *tmds_div);
 enum dc_status dcn401_enable_stream_timing(
@@ -48,10 +47,6 @@ enum dc_status dcn401_enable_stream_timing(
 				struct dc_state *context,
 				struct dc *dc);
 void dcn401_enable_stream(struct pipe_ctx *pipe_ctx);
-void dcn401_populate_mcm_luts(struct dc *dc,
-		struct pipe_ctx *pipe_ctx,
-		const struct dc_plane_cm *cm,
-		bool lut_bank_a);
 void dcn401_setup_hpo_hw_control(const struct dce_hwseq *hws, bool enable);
 
 void dcn401_disable_link_output(struct dc_link *link,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
index f206e221f926..7039f40ea880 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_init.c
@@ -166,7 +166,6 @@ static const struct hwseq_private_funcs dcn401_private_funcs = {
 	.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_pipe_sequence = dcn401_program_pipe_sequence,
 	.dc_ip_request_cntl = dcn401_dc_ip_request_cntl,
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
index 151a29bf0e9d..13580d9f9303 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
@@ -402,64 +402,6 @@ void dcn42_program_cm_hist(
 			plane_state->cm_hist_control, plane_state->color_space);
 }
 
-static void dc_get_lut_xbar(
-	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)
-{
-	/* component_order was previously hard-coded to RGBA in local_mcm,
-	 * preserve identical behavior.
-	 */
-	*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;
-}
-
-static void dc_get_lut_mode(
-	enum dc_cm_lut_swizzle swizzle,
-	enum hubp_3dlut_fl_mode *mode,
-	enum hubp_3dlut_fl_addressing_mode *addr_mode)
-{
-	switch (swizzle) {
-	case CM_LUT_3D_SWIZZLE_LINEAR_RGB:
-		*mode = hubp_3dlut_fl_mode_native_1;
-		*addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
-		break;
-	case CM_LUT_3D_SWIZZLE_LINEAR_BGR:
-		*mode = hubp_3dlut_fl_mode_native_2;
-		*addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
-		break;
-	case CM_LUT_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_cm_lut_pixel_format dc_format,
-	enum hubp_3dlut_fl_format *format)
-{
-	switch (dc_format) {
-	case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB:
-		*format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
-		break;
-	case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB:
-		*format = hubp_3dlut_fl_format_unorm_12lsb_bitslice;
-		break;
-	case CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10:
-		*format = hubp_3dlut_fl_format_float_fp1_5_10;
-		break;
-	default:
-		*format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
-		break;
-	}
-}
-
 static bool dc_is_rmcm_3dlut_supported(struct hubp *hubp, struct mpc *mpc)
 {
 	if (mpc->funcs->rmcm.power_on_shaper_3dlut &&
@@ -470,106 +412,17 @@ static bool dc_is_rmcm_3dlut_supported(struct hubp *hubp, struct mpc *mpc)
 	return false;
 }
 
-static bool is_rmcm_3dlut_fl_supported(struct dc *dc)
-{
-	/* size was previously hard-coded to TRANSFORMED in local_mcm,
-	 * which mapped to dim_17. Preserve identical behavior.
-	 */
-	if (!dc->caps.color.mpc.rmcm_3d_lut_caps.dma_3d_lut)
-		return false;
-	return dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_17 != 0u;
-}
-
-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)
-{
-	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 = MPCC_MOVABLE_CM_LOCATION_BEFORE;
-
-	*lut1d_xable = pipe_ctx->plane_state->cm.flags.bits.blend_enable ?
-		MCM_LUT_ENABLE : MCM_LUT_DISABLE;
-	*shaper_xable = pipe_ctx->plane_state->cm.flags.bits.shaper_enable ?
-		MCM_LUT_ENABLE : MCM_LUT_DISABLE;
-	*lut3d_xable = (pipe_ctx->plane_state->cm.flags.bits.shaper_enable &&
-			pipe_ctx->plane_state->cm.flags.bits.lut3d_enable) ?
-		MCM_LUT_ENABLE : MCM_LUT_DISABLE;
-}
-
-static void fl_get_lut_mode(
-	enum dc_cm_lut_swizzle swizzle,
-	enum hubp_3dlut_fl_mode *mode,
-	enum hubp_3dlut_fl_addressing_mode *addr_mode,
-	enum hubp_3dlut_fl_width *width)
-{
-	/* size was previously hard-coded to TRANSFORMED in local_mcm,
-	 * preserve identical behavior (transformed width).
-	 */
-	*width = hubp_3dlut_fl_width_17;
-
-	switch (swizzle) {
-	case CM_LUT_3D_SWIZZLE_LINEAR_RGB:
-		*mode = hubp_3dlut_fl_mode_native_1;
-		*addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
-		break;
-	case CM_LUT_3D_SWIZZLE_LINEAR_BGR:
-		*mode = hubp_3dlut_fl_mode_native_2;
-		*addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
-		break;
-	case CM_LUT_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,
 	const struct dc_plane_cm *cm,
 	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;
@@ -577,19 +430,24 @@ bool dcn42_program_rmcm_luts(
 	// 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);
 
+	bool lut_enable = false;
+	bool lut_bank_a = true;
+
 	//check to see current pipe is part of a stream with allocated rmcm 3dlut
 	if (!rmcm_3dlut)
 		return false;
 
-	/* rmcm_tmz was previously zero-initialized in local_mcm,
-	 * preserve identical behavior.
+	/* Determine the LUT bank currently active in HW and switch to the other
+	 * bank to preserve double-buffering (mirrors dcn401_set_mcm_luts).
 	 */
-	rmcm_3dlut->protection_bits = 0;
+	if (mpc->funcs->rmcm.get_3dlut_mode)
+		mpc->funcs->rmcm.get_3dlut_mode(mpc, mpcc_id, &lut_enable, &lut_bank_a);
 
-	dcn42_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable);
+	if (lut_enable)
+		lut_bank_a = !lut_bank_a;
 
 	/* Shaper */
-	{
+	if (cm->flags.bits.shaper_enable) {
 		memset(&m_lut_params, 0, sizeof(m_lut_params));
 
 		if (cm->shaper_func.type == TF_TYPE_HWPWL) {
@@ -615,56 +473,19 @@ bool dcn42_program_rmcm_luts(
 
 	/* 3DLUT */
 	if (!cm->flags.bits.lut3d_dma_enable) {
-		/* SYSMEM path — no DMA 3DLUT available.
-		 * Previously this was treated as a no-op for the DMA/VIDMEM
-		 * programming, preserve identical behavior.
+		/* RMCM host (non-DMA) 3DLUT load is not implemented; fail fast
+		 * instead of silently reporting success
 		 */
-		memset(&m_lut_params, 0, sizeof(m_lut_params));
+		BREAK_TO_DEBUGGER();
+		return false;
 	} else {
-		/* VIDMEM (3DLUT DMA Fast Load) */
-
-		fl_get_lut_mode(cm->lut3d_dma.swizzle,
-				&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))
+		if (!dc_is_rmcm_3dlut_supported(hubp, mpc))
 			return false;
 
-		// setting native or transformed mode,
-		dc_get_lut_mode(cm->lut3d_dma.swizzle, &mode, &addr_mode);
-
 		//seems to be only for the MCM
-		dc_get_lut_format(cm->lut3d_dma.format, &format);
-
-		dc_get_lut_xbar(
-			&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				= cm->lut3d_dma.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                = cm->lut3d_dma.swizzle;
-		fl_config.bias	= cm->lut3d_dma.bias;
-		fl_config.scale	= cm->lut3d_dma.scale;
-
-		mpc_fl_config.enabled			= fl_config.enabled;
-		mpc_fl_config.width	            = width;
+		mpc_fl_config.enabled			= cm->flags.bits.lut3d_enable != 0u;
+		mpc_fl_config.size	            = cm->lut3d_dma.size;
 		mpc_fl_config.select_lut_bank_a = lut_bank_a;
-		/* bit_depth was previously zero-initialized in local_mcm,
-		 * preserve identical behavior.
-		 */
 		mpc_fl_config.bit_depth		    = 0;
 		mpc_fl_config.hubp_index		= hubp->inst;
 		mpc_fl_config.bias	= cm->lut3d_dma.bias;
@@ -676,7 +497,12 @@ bool dcn42_program_rmcm_luts(
 		//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);
+		/* HUBP */
+		if (hubp->funcs->hubp_program_3dlut_fl_config)
+			hubp->funcs->hubp_program_3dlut_fl_config(hubp, &cm->lut3d_dma);
+
+		if (hubp->funcs->hubp_program_3dlut_fl_addr)
+			hubp->funcs->hubp_program_3dlut_fl_addr(hubp, &cm->lut3d_dma.addr);
 
 		//3. power on the block
 		mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, true);
@@ -685,261 +511,31 @@ bool dcn42_program_rmcm_luts(
 	return true;
 }
 
-void dcn42_populate_mcm_luts(struct dc *dc,
-		struct pipe_ctx *pipe_ctx,
-		const struct dc_plane_cm *cm,
-		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;
-	const bool lut3d_dma = !!cm->flags.bits.lut3d_dma_enable;
-	enum hubp_3dlut_fl_format format = 0;
-	enum hubp_3dlut_fl_mode mode;
-	/* Width was previously hard-coded to TRANSFORMED via local_mcm build,
-	 * preserve identical behavior.
-	 */
-	enum hubp_3dlut_fl_width width = hubp_3dlut_fl_width_transformed;
-	enum hubp_3dlut_fl_addressing_mode addr_mode;
-	enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g;
-	enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b;
-	enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r;
-	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
-	//mpc_mcm_post_blend was previously zero-initialized in local_mcm,
-	//preserve identical behavior.
-	dcn42_set_mcm_location_post_blend(
-		dc,
-		pipe_ctx,
-		false);
-
-	//RMCM - 3dLUT+Shaper
-	if (cm->flags.bits.rmcm_enable &&
-		is_rmcm_3dlut_fl_supported(dc))
-		dcn42_program_rmcm_luts(
-			hubp,
-			pipe_ctx,
-			cm,
-			mpc,
-			lut_bank_a,
-			mpcc_id);
-
-	/* 1D LUT */
-	{
-		memset(&m_lut_params, 0, sizeof(m_lut_params));
-		if (cm->blend_func.type == TF_TYPE_HWPWL)
-			m_lut_params.pwl = &cm->blend_func.pwl;
-		else if (cm->blend_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
-			rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx,
-					&cm->blend_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 (cm->flags.bits.lut3d_enable) {
-		memset(&m_lut_params, 0, sizeof(m_lut_params));
-		if (cm->shaper_func.type == TF_TYPE_HWPWL)
-			m_lut_params.pwl = &cm->shaper_func.pwl;
-		else if (cm->shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
-			ASSERT(false);
-			rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx,
-					&cm->shaper_func,
-					&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 */
-	if (!lut3d_dma) {
-		/* SYSMEM (legacy lut3d_func) */
-		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 (cm->lut3d_func.state.bits.initialized) {
-			m_lut_params.lut3d = &cm->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);
-		}
-	} else {
-		/* VIDMEM (3DLUT DMA Fast Load) */
-
-		//check for support
-		if (mpc->funcs->mcm.is_config_supported &&
-			!mpc->funcs->mcm.is_config_supported(width))
-			return;
-
-		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, cm->lut3d_dma.addr);
-
-		/* bit_depth was previously zero-initialized in local_mcm,
-		 * preserve identical behavior.
-		 */
-		if (mpc->funcs->mcm.program_bit_depth)
-			mpc->funcs->mcm.program_bit_depth(mpc, 0, mpcc_id);
-
-		switch (cm->lut3d_dma.swizzle) {
-		case CM_LUT_3D_SWIZZLE_LINEAR_RGB:
-			mode = hubp_3dlut_fl_mode_native_1;
-			addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
-			break;
-		case CM_LUT_3D_SWIZZLE_LINEAR_BGR:
-			mode = hubp_3dlut_fl_mode_native_2;
-			addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
-			break;
-		case CM_LUT_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;
-		}
-		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 (cm->lut3d_dma.format) {
-		case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB:
-			format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
-			break;
-		case CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB:
-			format = hubp_3dlut_fl_format_unorm_12lsb_bitslice;
-			break;
-		case CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10:
-			format = hubp_3dlut_fl_format_float_fp1_5_10;
-			break;
-		default:
-			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,
-				cm->lut3d_dma.bias,
-				cm->lut3d_dma.scale,
-				mpcc_id);
-			hubp->funcs->hubp_update_3dlut_fl_bias_scale(hubp,
-				cm->lut3d_dma.bias,
-				cm->lut3d_dma.scale);
-		}
-
-		/* component_order was previously hard-coded to RGBA in local_mcm,
-		 * preserve identical behavior.
-		 */
-		crossbar_bit_slice_cr_r = hubp_3dlut_fl_crossbar_bit_slice_0_15;
-		crossbar_bit_slice_y_g = hubp_3dlut_fl_crossbar_bit_slice_16_31;
-		crossbar_bit_slice_cb_b = hubp_3dlut_fl_crossbar_bit_slice_32_47;
-
-		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);
-			}
-		}
-	}
-}
-
 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->cm.flags.bits.lut3d_dma_enable) {
-		dcn42_populate_mcm_luts(dc, pipe_ctx, &plane_state->cm, 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->cm.blend_func.type == TF_TYPE_HWPWL)
-		lut_params = &plane_state->cm.blend_func.pwl;
-	else if (plane_state->cm.blend_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
-		rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
-				&plane_state->cm.blend_func,
-				&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->cm.shaper_func.type == TF_TYPE_HWPWL)
-		lut_params = &plane_state->cm.shaper_func.pwl;
-	else if (plane_state->cm.shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
-		// TODO: dpp_base replace
-		rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
-				&plane_state->cm.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);
+	/* MCM */
+	result = dcn401_set_mcm_luts(pipe_ctx, plane_state);
 
-	// 3D
-	if (mpc->funcs->program_3dlut) {
-		if (plane_state->cm.lut3d_func.state.bits.initialized == 1)
-			result &= mpc->funcs->program_3dlut(mpc, &plane_state->cm.lut3d_func.lut_3d, mpcc_id);
-		else
-			result &= mpc->funcs->program_3dlut(mpc, NULL, mpcc_id);
+	/* RMCM */
+	{
+		struct dc *dc = pipe_ctx->plane_res.hubp->ctx->dc;
+		struct hubp *hubp = pipe_ctx->plane_res.hubp;
+		const struct dc_plane_cm *cm = &plane_state->cm;
+		struct mpc *mpc = dc->res_pool->mpc;
+		int mpcc_id = hubp->inst;
+
+		if (cm->flags.bits.rmcm_enable && cm->flags.bits.lut3d_dma_enable) {
+			/* TODO - move RMCM to its own block */
+			dcn42_program_rmcm_luts(
+				hubp,
+				pipe_ctx,
+				cm,
+				mpc,
+				mpcc_id);
+		}
 	}
 
 	return result;
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
index c469e7535114..c4cfeed45b19 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h
@@ -18,17 +18,11 @@ void dcn42_program_cm_hist(
 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,
-		const struct dc_plane_cm *cm,
-		bool lut_bank_a);
-
 bool dcn42_program_rmcm_luts(
 	struct hubp *hubp,
 	struct pipe_ctx *pipe_ctx,
 	const struct dc_plane_cm *cm,
 	struct mpc *mpc,
-	bool lut_bank_a,
 	int mpcc_id);
 void dcn42_hardware_release(struct dc *dc);
 
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
index 49c13611a518..ba12a97a220f 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c
@@ -155,8 +155,6 @@ static const struct hwseq_private_funcs dcn42_private_funcs = {
 	.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,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
index 5f4f32d516d5..1c908964153b 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
@@ -166,8 +166,6 @@ static const struct hwseq_private_funcs dcn60_private_funcs = {
 	.calculate_dccg_k1_k2_values = NULL,
 	.apply_single_controller_ctx_to_hw = dcn60_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,
 	.program_pipe = dcn401_program_pipe,
 	.program_pipe_sequence = dcn401_program_pipe_sequence,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index c4296b8390f2..cdf2562a9a40 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -1506,7 +1506,7 @@ struct hw_sequencer_funcs {
 	void (*program_output_csc)(struct dc *dc, struct pipe_ctx *pipe_ctx,
 			enum dc_color_space colorspace,
 			uint16_t *matrix, int opp_id);
-	void (*trigger_3dlut_dma_load)(struct dc *dc, struct pipe_ctx *pipe_ctx);
+	void (*trigger_3dlut_dma_load)(struct pipe_ctx *pipe_ctx);
 
 	/* VM Related */
 	int (*init_sys_ctx)(struct dce_hwseq *hws,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h
index 31ace62a37d9..0f7881a21462 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h
@@ -58,7 +58,6 @@ struct dc_state;
 struct dc_stream_status;
 struct dc_writeback_info;
 struct dchub_init_data;
-struct dc_plane_cm;
 struct dc_static_screen_params;
 struct resource_pool;
 struct resource_context;
@@ -218,10 +217,6 @@ struct hwseq_private_funcs {
 	void (*reset_back_end_for_pipe)(struct dc *dc,
 			struct pipe_ctx *pipe_ctx,
 			struct dc_state *context);
-	void (*populate_mcm_luts)(struct dc *dc,
-			struct pipe_ctx *pipe_ctx,
-			const struct dc_plane_cm *cm,
-			bool lut_bank_a);
 	void (*perform_3dlut_wa_unlock)(struct pipe_ctx *pipe_ctx);
 	void (*wait_for_pipe_update_if_needed)(struct dc *dc, struct pipe_ctx *pipe_ctx, bool is_surface_update_only);
 	void (*set_wait_for_update_needed_for_pipe)(struct dc *dc, struct pipe_ctx *pipe_ctx);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
index 6d6eda0e7e9d..9dc9317c28a4 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h
@@ -89,7 +89,7 @@ enum hubp_3dlut_fl_addressing_mode {
 enum hubp_3dlut_fl_width {
 	hubp_3dlut_fl_width_17 = 17,
 	hubp_3dlut_fl_width_33 = 33,
-	hubp_3dlut_fl_width_transformed    = 4916, //mpc default
+	hubp_3dlut_fl_width_17_transformed    = 4916, //mpc default
 };
 
 enum hubp_3dlut_fl_crossbar_bit_slice {
@@ -99,22 +99,6 @@ enum hubp_3dlut_fl_crossbar_bit_slice {
 	hubp_3dlut_fl_crossbar_bit_slice_48_63 = 3
 };
 
-struct hubp_fl_3dlut_config {
-	bool enabled;
-	enum hubp_3dlut_fl_width width;
-	enum hubp_3dlut_fl_mode mode;
-	enum hubp_3dlut_fl_format format;
-	uint16_t bias;
-	uint16_t scale;
-	struct dc_plane_address address;
-	enum hubp_3dlut_fl_addressing_mode addr_mode;
-	enum dc_cm_lut_swizzle layout;
-	uint8_t protection_bits;
-	enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g;
-	enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b;
-	enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r;
-};
-
 struct hubp {
 	const struct hubp_funcs *funcs;
 	struct dc_context *ctx;
@@ -289,24 +273,15 @@ struct hubp_funcs {
 
 	void (*hubp_wait_pipe_read_start)(struct hubp *hubp);
 	void (*hubp_program_mcache_id_and_split_coordinate)(struct hubp *hubp, struct dml2_hubp_pipe_mcache_regs *mcache_regs);
-	void (*hubp_update_3dlut_fl_bias_scale)(struct hubp *hubp, uint16_t bias, uint16_t scale);
-	void (*hubp_program_3dlut_fl_mode)(struct hubp *hubp,
-			enum hubp_3dlut_fl_mode mode);
-	void (*hubp_program_3dlut_fl_format)(struct hubp *hubp,
-			enum hubp_3dlut_fl_format format);
 	void (*hubp_program_3dlut_fl_addr)(struct hubp *hubp,
-		const struct dc_plane_address address);
+		const struct dc_plane_address *address);
+	void (*hubp_program_3dlut_fl_config)(struct hubp *hubp,
+		const struct dc_3dlut_dma *config);
 	void (*hubp_program_3dlut_fl_dlg_param)(struct hubp *hubp, int refcyc_per_3dlut_group);
 	void (*hubp_enable_3dlut_fl)(struct hubp *hubp, bool enable);
-	void (*hubp_program_3dlut_fl_addressing_mode)(struct hubp *hubp, enum hubp_3dlut_fl_addressing_mode addr_mode);
-	void (*hubp_program_3dlut_fl_width)(struct hubp *hubp, enum hubp_3dlut_fl_width width);
-	void (*hubp_program_3dlut_fl_tmz_protected)(struct hubp *hubp, uint8_t protection_bits);
 	void (*hubp_program_3dlut_fl_crossbar)(struct hubp *hubp,
-			enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_y_g,
-			enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cb_b,
-			enum hubp_3dlut_fl_crossbar_bit_slice bit_slice_cr_r);
+			enum dc_cm_lut_pixel_format format);
 	uint32_t (*hubp_get_3dlut_fl_done)(struct hubp *hubp);
-	void (*hubp_program_3dlut_fl_config)(struct hubp *hubp, struct hubp_fl_3dlut_config *cfg);
 	void (*hubp_clear_tiling)(struct hubp *hubp);
 	uint32_t (*hubp_get_current_read_line)(struct hubp *hubp);
 	uint32_t (*hubp_get_det_config_error)(struct hubp *hubp);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h
index 54eb2eba68bf..d863f4bdccad 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h
@@ -54,6 +54,7 @@
 #include "dc_hw_types.h"
 #include "hw_shared.h"
 #include "transform.h"
+#include "dc_types.h"
 
 #define MAX_MPCC 6
 #define MAX_OPP 6
@@ -101,13 +102,6 @@ enum mpcc_movable_cm_location {
 	MPCC_MOVABLE_CM_LOCATION_AFTER,
 };
 
-enum MCM_LUT_XABLE {
-	MCM_LUT_DISABLE,
-	MCM_LUT_DISABLED = MCM_LUT_DISABLE,
-	MCM_LUT_ENABLE,
-	MCM_LUT_ENABLED = MCM_LUT_ENABLE,
-};
-
 enum MCM_LUT_ID {
 	MCM_LUT_3DLUT,
 	MCM_LUT_1DLUT,
@@ -116,7 +110,7 @@ enum MCM_LUT_ID {
 
 struct mpc_fl_3dlut_config {
 	bool enabled;
-	uint16_t width;
+	enum dc_cm_lut_size size;
 	bool select_lut_bank_a;
 	uint16_t bit_depth;
 	int hubp_index;
@@ -1075,8 +1069,11 @@ struct mpc_funcs {
 	*
 	* void
 	*/
-	void (*populate_lut)(struct mpc *mpc, const enum MCM_LUT_ID id, const union mcm_lut_params params,
-			bool lut_bank_a, int mpcc_id);
+	void (*populate_lut)(struct mpc *mpc,
+			const enum MCM_LUT_ID id,
+			const union mcm_lut_params *params,
+			const bool lut_bank_a,
+			const int mpcc_id);
 
 	/**
 	* @program_lut_read_write_control:
@@ -1087,13 +1084,18 @@ struct mpc_funcs {
 	* - [in/out] mpc - MPC context.
 	* - [in] id
 	* - [in] lut_bank_a
+	* - [in] bit_depth
 	* - [in] mpcc_id
 	*
 	* Return:
 	*
 	* void
 	*/
-	void (*program_lut_read_write_control)(struct mpc *mpc, const enum MCM_LUT_ID id, bool lut_bank_a, int mpcc_id);
+	void (*program_lut_read_write_control)(struct mpc *mpc,
+		const enum MCM_LUT_ID id,
+		const bool lut_bank_a,
+		const unsigned int bit_depth,
+		const int mpcc_id);
 
 	/**
 	* @program_lut_mode:
@@ -1103,33 +1105,44 @@ struct mpc_funcs {
 	* Parameters:
 	* - [in/out] mpc - MPC context.
 	* - [in] id
-	* - [in] xable
+	* - [in] enable
 	* - [in] lut_bank_a
+	* - [in] size
 	* - [in] mpcc_id
 	*
 	* Return:
 	*
 	* void
 	*/
-	void (*program_lut_mode)(struct mpc *mpc, const enum MCM_LUT_ID id, const enum MCM_LUT_XABLE xable,
-			bool lut_bank_a, int mpcc_id);
+	void (*program_lut_mode)(struct mpc *mpc,
+			const enum MCM_LUT_ID id,
+			const bool enable,
+			const bool lut_bank_a,
+			const enum dc_cm_lut_size size,
+			const int mpcc_id);
 
-	/**
-	 * @mcm:
-	 *
-	 * MPC MCM new HW sequential programming functions
-	 */
-	struct {
-		void (*program_3dlut_size)(struct mpc *mpc, uint32_t width, int mpcc_id);
-		void (*program_bias_scale)(struct mpc *mpc, uint16_t bias, uint16_t scale, int mpcc_id);
-		void (*program_bit_depth)(struct mpc *mpc, uint16_t bit_depth, int mpcc_id);
-		bool (*is_config_supported)(uint32_t width);
-		void (*program_lut_read_write_control)(struct mpc *mpc, const enum MCM_LUT_ID id,
-			bool lut_bank_a, bool enabled, int mpcc_id);
 
-		void (*populate_lut)(struct mpc *mpc, const union mcm_lut_params params,
-			bool lut_bank_a, int mpcc_id);
-	} mcm;
+	/**
+	* @get_lut_mode:
+	*
+	* Obtains enablement and ram bank status.
+	*
+	* Parameters:
+	* - [in/out] mpc - MPC context.
+	* - [in] id
+	* - [in] mpcc_id
+	* - [out] enable
+	* - [out] lut_bank_a
+	*
+	* Return:
+	*
+	* void
+	*/
+	void (*get_lut_mode)(struct mpc *mpc,
+			const enum MCM_LUT_ID id,
+			const int mpcc_id,
+			bool *enable,
+			bool *lut_bank_a);
 
 	/**
 	 * @rmcm:
@@ -1142,9 +1155,11 @@ struct mpc_funcs {
 		void (*update_3dlut_fast_load_select)(struct mpc *mpc, int mpcc_id, int hubp_idx);
 		void (*program_lut_read_write_control)(struct mpc *mpc, const enum MCM_LUT_ID id,
 			bool lut_bank_a, bool enabled, int mpcc_id);
-		void (*program_lut_mode)(struct mpc *mpc, const enum MCM_LUT_XABLE xable,
-			bool lut_bank_a, int mpcc_id);
-		void (*program_3dlut_size)(struct mpc *mpc, uint32_t width, int mpcc_id);
+		void (*program_lut_mode)(struct mpc *mpc,
+			bool enable,
+			bool lut_bank_a,
+			int mpcc_id);
+		void (*program_3dlut_size)(struct mpc *mpc, const enum dc_cm_lut_size size, int mpcc_id);
 		void (*program_bias_scale)(struct mpc *mpc, uint16_t bias, uint16_t scale, int mpcc_id);
 		void (*program_bit_depth)(struct mpc *mpc, uint16_t bit_depth, int mpcc_id);
 		bool (*is_config_supported)(uint32_t width);
@@ -1152,6 +1167,8 @@ struct mpc_funcs {
 		void (*power_on_shaper_3dlut)(struct mpc *mpc, uint32_t mpcc_id, bool power_on);
 		void (*populate_lut)(struct mpc *mpc, const union mcm_lut_params params,
 			bool lut_bank_a, int mpcc_id);
+		void (*get_3dlut_mode)(struct mpc *mpc, int mpcc_id,
+			bool *enable, bool *lut_bank_a);
 	} rmcm;
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c
index d8a4e604a34e..df92d8008fe6 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c
@@ -73,56 +73,15 @@ void mpc401_set_movable_cm_location(struct mpc *mpc, enum mpcc_movable_cm_locati
 	}
 }
 
-static enum dc_lut_mode get3dlut_config(
-			struct mpc *mpc,
-			bool *is_17x17x17,
-			bool *is_12bits_color_channel,
-			int mpcc_id)
-{
-	uint32_t i_mode, i_enable_10bits, lut_size;
-	enum dc_lut_mode mode;
-	struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc);
-
-	REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id],
-			MPCC_MCM_3DLUT_MODE_CURRENT,  &i_mode);
-
-	REG_GET(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
-			MPCC_MCM_3DLUT_30BIT_EN, &i_enable_10bits);
-
-	switch (i_mode) {
-	case 0:
-		mode = LUT_BYPASS;
-		break;
-	case 1:
-		mode = LUT_RAM_A;
-		break;
-	case 2:
-		mode = LUT_RAM_B;
-		break;
-	default:
-		mode = LUT_BYPASS;
-		break;
-	}
-	if (i_enable_10bits > 0)
-		*is_12bits_color_channel = false;
-	else
-		*is_12bits_color_channel = true;
-
-	REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE, &lut_size);
-
-	if (lut_size == 0)
-		*is_17x17x17 = true;
-	else
-		*is_17x17x17 = false;
-
-	return mode;
-}
-
-void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union mcm_lut_params params, bool lut_bank_a, int mpcc_id)
+void mpc401_populate_lut(struct mpc *mpc,
+		const enum MCM_LUT_ID id,
+		const union mcm_lut_params *params,
+		const bool lut_bank_a,
+		const int mpcc_id)
 {
 	const enum dc_lut_mode next_mode = lut_bank_a ? LUT_RAM_A : LUT_RAM_B;
-	const struct pwl_params *lut1d = params.pwl;
-	const struct pwl_params *lut_shaper = params.pwl;
+	const struct pwl_params *lut1d = params->pwl;
+	const struct pwl_params *lut_shaper = params->pwl;
 	bool is_17x17x17;
 	bool is_12bits_color_channel;
 	const struct dc_rgb *lut0;
@@ -131,7 +90,7 @@ void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union
 	const struct dc_rgb *lut3;
 	int lut_size0;
 	int lut_size;
-	const struct tetrahedral_params *lut3d = params.lut3d;
+	const struct tetrahedral_params *lut3d = params->lut3d;
 
 	switch (id) {
 	case MCM_LUT_1DLUT:
@@ -174,8 +133,6 @@ void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union
 
 		mpc32_power_on_shaper_3dlut(mpc, mpcc_id, true);
 
-		get3dlut_config(mpc, &is_17x17x17, &is_12bits_color_channel, mpcc_id);
-
 		is_17x17x17 = !lut3d->use_tetrahedral_9;
 		is_12bits_color_channel = lut3d->use_12bits;
 		if (is_17x17x17) {
@@ -198,8 +155,6 @@ void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union
 					sizeof(lut3d->tetrahedral_9.lut1[0]);
 			}
 
-		mpc32_select_3dlut_ram(mpc, next_mode,
-					is_12bits_color_channel, mpcc_id);
 		mpc32_select_3dlut_ram_mask(mpc, 0x1, mpcc_id);
 		if (is_12bits_color_channel)
 			mpc32_set3dlut_ram12(mpc, lut0, lut_size0, mpcc_id);
@@ -232,46 +187,69 @@ void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union
 
 }
 
+static uint32_t mpc401_cm_lut_size_to_3dlut_size(const enum dc_cm_lut_size cm_size)
+{
+	uint32_t size = 0;
+
+	switch (cm_size) {
+	case CM_LUT_SIZE_999:
+		size = 1;
+		break;
+	case CM_LUT_SIZE_171717:
+		size = 0;
+		break;
+	default:
+		/* invalid LUT size */
+		ASSERT(false);
+		size = 0;
+		break;
+	}
+
+	return size;
+}
+
 void mpc401_program_lut_mode(
 		struct mpc *mpc,
 		const enum MCM_LUT_ID id,
-		const enum MCM_LUT_XABLE xable,
-		bool lut_bank_a,
-		int mpcc_id)
+		const bool enable,
+		const bool lut_bank_a,
+		const enum dc_cm_lut_size size,
+		const int mpcc_id)
 {
+	uint32_t lut_size;
 	struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc);
 
 	switch (id) {
 	case MCM_LUT_3DLUT:
-		switch (xable) {
-		case MCM_LUT_DISABLE:
+		if (enable) {
+			lut_size = mpc401_cm_lut_size_to_3dlut_size(size);
+			REG_UPDATE_2(MPCC_MCM_3DLUT_MODE[mpcc_id],
+					MPCC_MCM_3DLUT_MODE, lut_bank_a ? 1 : 2,
+					MPCC_MCM_3DLUT_SIZE, lut_size);
+		} else {
+			if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
+				mpc32_power_on_shaper_3dlut(mpc, mpcc_id, false);
 			REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_MODE, 0);
-			break;
-		case MCM_LUT_ENABLE:
-			REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_MODE, lut_bank_a ? 1 : 2);
-			break;
 		}
 		break;
 	case MCM_LUT_SHAPER:
-		switch (xable) {
-		case MCM_LUT_DISABLE:
-			REG_UPDATE(MPCC_MCM_SHAPER_CONTROL[mpcc_id], MPCC_MCM_SHAPER_LUT_MODE, 0);
-			break;
-		case MCM_LUT_ENABLE:
+		if (enable) {
 			REG_UPDATE(MPCC_MCM_SHAPER_CONTROL[mpcc_id], MPCC_MCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2);
-			break;
+		} else {
+			if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
+				mpc32_power_on_shaper_3dlut(mpc, mpcc_id, false);
+			REG_UPDATE(MPCC_MCM_SHAPER_CONTROL[mpcc_id], MPCC_MCM_SHAPER_LUT_MODE, 0);
 		}
 		break;
 	case MCM_LUT_1DLUT:
-		switch (xable) {
-		case MCM_LUT_DISABLE:
-			REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
-					MPCC_MCM_1DLUT_MODE, 0);
-			break;
-		case MCM_LUT_ENABLE:
+		if (enable) {
 			REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
 					MPCC_MCM_1DLUT_MODE, 2);
-			break;
+		} else {
+			if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
+				mpc32_power_on_blnd_lut(mpc, mpcc_id, false);
+			REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
+					MPCC_MCM_1DLUT_MODE, 0);
 		}
 		REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
 				MPCC_MCM_1DLUT_SELECT, lut_bank_a ? 0 : 1);
@@ -279,14 +257,20 @@ void mpc401_program_lut_mode(
 	}
 }
 
-void mpc401_program_lut_read_write_control(struct mpc *mpc, const enum MCM_LUT_ID id, bool lut_bank_a, int mpcc_id)
+void mpc401_program_lut_read_write_control(struct mpc *mpc,
+		const enum MCM_LUT_ID id,
+		const bool lut_bank_a,
+		const unsigned int bit_depth,
+		const int mpcc_id)
 {
 	struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc);
 
 	switch (id) {
 	case MCM_LUT_3DLUT:
 		mpc32_select_3dlut_ram_mask(mpc, 0xf, mpcc_id);
-		REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPCC_MCM_3DLUT_RAM_SEL, lut_bank_a ? 0 : 1);
+		REG_UPDATE_2(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+				MPCC_MCM_3DLUT_30BIT_EN, (bit_depth == 10) ? 1 : 0,
+				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);
@@ -605,6 +589,44 @@ void mpc401_get_gamut_remap(struct mpc *mpc,
 			coef_format, ARRAY_SIZE(arr_reg_val));
 }
 
+void mpc401_get_lut_mode(struct mpc *mpc,
+		const enum MCM_LUT_ID id,
+		const int mpcc_id,
+		bool *enable,
+		bool *lut_bank_a)
+{
+	struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc);
+
+	uint32_t lut_mode = 0;
+	uint32_t lut_select = 0;
+
+	*enable = false;
+	*lut_bank_a = true;
+
+	switch (id) {
+	case MCM_LUT_SHAPER:
+		REG_GET(MPCC_MCM_SHAPER_CONTROL[mpcc_id],
+				MPCC_MCM_SHAPER_MODE_CURRENT, &lut_mode);
+		*enable = lut_mode != 0;
+		*lut_bank_a = lut_mode != 2;
+		break;
+	case MCM_LUT_1DLUT:
+		REG_GET_2(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
+				MPCC_MCM_1DLUT_MODE_CURRENT, &lut_mode,
+				MPCC_MCM_1DLUT_SELECT_CURRENT, &lut_select);
+		*enable = lut_mode != 0;
+		*lut_bank_a = lut_mode == 0 || lut_select == 0;
+		break;
+	case MCM_LUT_3DLUT:
+	default:
+		REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id],
+				MPCC_MCM_3DLUT_MODE_CURRENT, &lut_mode);
+		*enable = lut_mode != 0;
+		*lut_bank_a = lut_mode != 2;
+		break;
+	}
+}
+
 static const struct mpc_funcs dcn401_mpc_funcs = {
 	.read_mpcc_state = mpc1_read_mpcc_state,
 	.insert_plane = mpc1_insert_plane,
@@ -643,6 +665,7 @@ static const struct mpc_funcs dcn401_mpc_funcs = {
 	.populate_lut = mpc401_populate_lut,
 	.program_lut_read_write_control = mpc401_program_lut_read_write_control,
 	.program_lut_mode = mpc401_program_lut_mode,
+	.get_lut_mode = mpc401_get_lut_mode,
 };
 
 
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h
index 3d00d9497ed2..75fa05ed2b22 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h
@@ -206,21 +206,32 @@ void dcn401_mpc_construct(struct dcn401_mpc *mpc401,
 	int num_rmu);
 
 void mpc401_set_movable_cm_location(struct mpc *mpc, enum mpcc_movable_cm_location location, int mpcc_id);
-void mpc401_populate_lut(struct mpc *mpc, const enum MCM_LUT_ID id, const union mcm_lut_params params,
-		bool lut_bank_a, int mpcc_id);
+void mpc401_populate_lut(struct mpc *mpc,
+		const enum MCM_LUT_ID id,
+		const union mcm_lut_params *params,
+		bool lut_bank_a,
+		int mpcc_id);
 
 void mpc401_program_lut_mode(
 		struct mpc *mpc,
 		const enum MCM_LUT_ID id,
-		const enum MCM_LUT_XABLE xable,
-		bool lut_bank_a,
-		int mpcc_id);
+		const bool enable,
+		const bool lut_bank_a,
+		const enum dc_cm_lut_size size,
+		const int mpcc_id);
+
+void mpc401_get_lut_mode(struct mpc *mpc,
+		const enum MCM_LUT_ID id,
+		const int mpcc_id,
+		bool *enable,
+		bool *lut_bank_a);
 
 void mpc401_program_lut_read_write_control(
 		struct mpc *mpc,
 		const enum MCM_LUT_ID id,
-		bool lut_bank_a,
-		int mpcc_id);
+		const bool lut_bank_a,
+		const unsigned int bit_depth,
+		const int mpcc_id);
 
 void mpc401_set_gamut_remap(
 	struct mpc *mpc,
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
index 38c0e8f96d40..5a888e1e1cc5 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c
@@ -63,154 +63,6 @@ void mpc42_update_blending(
 	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,
@@ -674,32 +526,47 @@ void mpc42_program_rmcm_lut_read_write_control(struct mpc *mpc, const enum MCM_L
 	}
 }
 
-void mpc42_program_lut_mode(struct mpc *mpc, const enum MCM_LUT_XABLE xable,
-	bool lut_bank_a, int mpcc_id)
+void mpc42_program_lut_mode(struct mpc *mpc,
+	bool enable,
+	bool lut_bank_a,
+	int mpcc_id)
 {
 	struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
 
-	switch (xable) {
-	case MCM_LUT_DISABLE:
+	if (enable) {
+		REG_UPDATE(MPC_RMCM_SHAPER_CONTROL[mpcc_id], MPC_RMCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2);
+	} else {
 		REG_UPDATE(MPC_RMCM_SHAPER_CONTROL[mpcc_id], MPC_RMCM_SHAPER_LUT_MODE, 0);
+	}
+}
+
+static uint32_t mpc42_get_rmcm_3dlut_width(
+		const enum dc_cm_lut_size size)
+{
+	uint32_t width = 0;
+
+	switch (size) {
+	case CM_LUT_SIZE_333333:
+		width = 2;
 		break;
-	case MCM_LUT_ENABLE:
-		REG_UPDATE(MPC_RMCM_SHAPER_CONTROL[mpcc_id], MPC_RMCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2);
+	case CM_LUT_SIZE_171717:
+	default:
+		width = 0;
 		break;
 	}
+
+	return width;
 }
 
-void mpc42_program_rmcm_3dlut_size(struct mpc *mpc, uint32_t width, int mpcc_id)
+void mpc42_program_rmcm_3dlut_size(struct mpc *mpc,
+		const enum dc_cm_lut_size size,
+		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);
+	uint32_t width = mpc42_get_rmcm_3dlut_width(size);
 
-	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);
 }
 
 void mpc42_program_rmcm_3dlut_fast_load_bias_scale(struct mpc *mpc, uint16_t bias, uint16_t scale, int mpcc_id)
@@ -731,14 +598,6 @@ void mpc42_program_rmcm_bit_depth(struct mpc *mpc, uint16_t bit_depth, int mpcc_
 		(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,
@@ -746,6 +605,7 @@ void mpc42_set_fl_config(
 {
 	struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
 
+	uint32_t width = mpc42_get_rmcm_3dlut_width(cfg->size);
 	/*
 	From: Jie Zhou
 
@@ -786,7 +646,7 @@ void mpc42_set_fl_config(
 
 	//width
 	REG_UPDATE_2(MPC_RMCM_3DLUT_MODE[mpcc_id],
-		MPC_RMCM_3DLUT_SIZE, (cfg->width == 33) ? 2 : 0,
+		MPC_RMCM_3DLUT_SIZE, width,
 		MPC_RMCM_3DLUT_MODE, (!cfg->enabled) ? 0 : (cfg->select_lut_bank_a) ? 1 : 2);
 
 	//connect to hubp
@@ -799,181 +659,23 @@ void mpc42_set_fl_config(
 	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_get_rmcm_3dlut_mode(
+	struct mpc *mpc,
+	int mpcc_id,
+	bool *enable,
+	bool *lut_bank_a)
+{
+	struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+	uint32_t mode_current   = 0;
+
+	REG_GET(MPC_RMCM_3DLUT_MODE[mpcc_id], MPC_RMCM_3DLUT_MODE_CURRENT, &mode_current);
+
+	/* MPC_RMCM_3DLUT_MODE encoding:
+	 *   0 -> disabled, 1 -> bank A, 2 -> bank B
+	 */
+	*enable     = mode_current != 0;
+	*lut_bank_a = mode_current != 2;
+}
 
 void mpc42_read_mpcc_state(
 		struct mpc *mpc,
@@ -1071,14 +773,7 @@ static const struct mpc_funcs dcn42_mpc_funcs = {
 	.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,
-	},
+	.get_lut_mode = mpc401_get_lut_mode,
 	.rmcm = {
 		.enable_3dlut_fl = mpc42_enable_3dlut_fl,
 		.update_3dlut_fast_load_select = mpc42_update_3dlut_fast_load_select,
@@ -1087,10 +782,10 @@ static const struct mpc_funcs dcn42_mpc_funcs = {
 		.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,
+		.get_3dlut_mode = mpc42_get_rmcm_3dlut_mode,
 	},
 };
 
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
index 12a12c28e553..af3b90af5396 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h
@@ -884,49 +884,6 @@ void dcn42_mpc_construct(struct dcn42_mpc *mpc401,
 
 void mpc42_init_mpcc(struct mpcc *mpcc, int mpcc_inst);
 
-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,
@@ -970,12 +927,12 @@ void mpc42_program_rmcm_lut_read_write_control(
 		int mpcc_id);
 void mpc42_program_lut_mode(
 		struct mpc *mpc,
-		const enum MCM_LUT_XABLE xable,
+		bool enable,
 		bool lut_bank_a,
 		int mpcc_id);
 void mpc42_program_rmcm_3dlut_size(
 		struct mpc *mpc,
-		uint32_t width,
+		const enum dc_cm_lut_size size,
 		int mpcc_id);
 void mpc42_program_rmcm_3dlut_fast_load_bias_scale(
 		struct mpc *mpc,
@@ -987,13 +944,17 @@ void mpc42_program_rmcm_bit_depth(
 		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_get_rmcm_3dlut_mode(
+	struct mpc *mpc,
+	int mpcc_id,
+	bool *enable,
+	bool *lut_bank_a);
+
 void mpc42_read_mpcc_state(
 		struct mpc *mpc,
 		int mpcc_inst,
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.c
index f8a878ead67d..2c0b92854a9c 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.c
@@ -139,165 +139,123 @@ void mpc60_program_rmcm_lut_read_write_control(struct mpc *mpc, const enum MCM_L
 	}
 }
 
-void mpc60_select_3dlut_ram(
-	struct mpc *mpc,
-	enum dc_lut_mode mode,
-	bool is_color_channel_12bits,
-	uint32_t mpcc_id)
+static void mpc60_program_lut_read_write_control(struct mpc *mpc,
+		const enum MCM_LUT_ID id,
+		const bool lut_bank_a,
+		const unsigned int bit_depth,
+		const int mpcc_id)
 {
-	(void)mode;
 	struct dcn60_mpc *mpc60 = TO_DCN60_MPC(mpc);
 
-	REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
-		MPCC_MCM_3DLUT_30BIT_EN, is_color_channel_12bits == true ? 0 : 1);
+	switch (id) {
+	case MCM_LUT_3DLUT:
+		mpc32_select_3dlut_ram_mask(mpc, 0xf, mpcc_id);
+		REG_UPDATE(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+				MPCC_MCM_3DLUT_30BIT_EN, (bit_depth == 10) ? 1 : 0);
+		break;
+	case MCM_LUT_SHAPER:
+		mpc32_configure_shaper_lut(mpc, lut_bank_a, mpcc_id);
+		break;
+	case MCM_LUT_1DLUT:
+		mpc32_configure_post1dlut(mpc, lut_bank_a, mpcc_id);
+		break;
+	}
 }
 
-static enum dc_lut_mode get3dlut_config(
-	struct mpc *mpc,
-	bool *is_17x17x17,
-	bool *is_12bits_color_channel,
-	int mpcc_id)
+static uint32_t mpc60_cm_lut_size_to_3dlut_size(const enum dc_cm_lut_size cm_size)
 {
-	uint32_t i_mode, i_enable_10bits, lut_size;
-	enum dc_lut_mode mode;
-	struct dcn60_mpc *mpc60 = TO_DCN60_MPC(mpc);
+	uint32_t size = 0;
 
-	REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id],
-		MPCC_MCM_3DLUT_MODE_CURRENT, &i_mode);
-
-	REG_GET(MPCC_MCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
-		MPCC_MCM_3DLUT_30BIT_EN, &i_enable_10bits);
-
-	switch (i_mode) {
-	case 0:
-		mode = LUT_BYPASS;
-		break;
-	case 1:
-		mode = LUT_RAM_A;
+	switch (cm_size) {
+	case CM_LUT_SIZE_999:
+		size = 1;
 		break;
-	case 2:
-		mode = LUT_RAM_B;
+	case CM_LUT_SIZE_171717:
+		size = 0;
 		break;
 	default:
-		mode = LUT_BYPASS;
+		/* invalid LUT size for MCM */
+		ASSERT(false);
+		size = 0;
 		break;
 	}
-	if (i_enable_10bits > 0)
-		*is_12bits_color_channel = false;
-	else
-		*is_12bits_color_channel = true;
-
-	REG_GET(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE, &lut_size);
-
-	if (lut_size == 0)
-		*is_17x17x17 = true;
-	else
-		*is_17x17x17 = false;
-
-	return mode;
-}
-
-bool mpc60_program_3dlut(
-	struct mpc *mpc,
-	const struct tetrahedral_params *params,
-	int mpcc_id)
-{
-	enum dc_lut_mode mode;
-	bool is_17x17x17;
-	bool is_12bits_color_channel;
-	const struct dc_rgb *lut0;
-	const struct dc_rgb *lut1;
-	const struct dc_rgb *lut2;
-	const struct dc_rgb *lut3;
-	int lut_size0;
-	int lut_size;
-
-	if (params == NULL) {
-		mpc32_set_3dlut_mode(mpc, LUT_BYPASS, false, false, mpcc_id);
-		return false;
-	}
-	mpc32_power_on_shaper_3dlut(mpc, mpcc_id, true);
-
-	mode = get3dlut_config(mpc, &is_17x17x17, &is_12bits_color_channel, mpcc_id);
-
-	if (mode == LUT_BYPASS || mode == LUT_RAM_B)
-		mode = LUT_RAM_A;
-	else
-		mode = LUT_RAM_B;
-
-	is_17x17x17 = !params->use_tetrahedral_9;
-	is_12bits_color_channel = params->use_12bits;
-	if (is_17x17x17) {
-		lut0 = params->tetrahedral_17.lut0;
-		lut1 = params->tetrahedral_17.lut1;
-		lut2 = params->tetrahedral_17.lut2;
-		lut3 = params->tetrahedral_17.lut3;
-		lut_size0 = sizeof(params->tetrahedral_17.lut0) /
-			sizeof(params->tetrahedral_17.lut0[0]);
-		lut_size = sizeof(params->tetrahedral_17.lut1) /
-			sizeof(params->tetrahedral_17.lut1[0]);
-	} else {
-		lut0 = params->tetrahedral_9.lut0;
-		lut1 = params->tetrahedral_9.lut1;
-		lut2 = params->tetrahedral_9.lut2;
-		lut3 = params->tetrahedral_9.lut3;
-		lut_size0 = sizeof(params->tetrahedral_9.lut0) /
-			sizeof(params->tetrahedral_9.lut0[0]);
-		lut_size = sizeof(params->tetrahedral_9.lut1) /
-			sizeof(params->tetrahedral_9.lut1[0]);
-	}
 
-	mpc60_select_3dlut_ram(mpc, mode,
-				is_12bits_color_channel, mpcc_id);
-	mpc32_select_3dlut_ram_mask(mpc, 0x1, mpcc_id);
-	if (is_12bits_color_channel)
-		mpc32_set3dlut_ram12(mpc, lut0, lut_size0, mpcc_id);
-	else
-		mpc32_set3dlut_ram10(mpc, lut0, lut_size0, mpcc_id);
-
-	mpc32_select_3dlut_ram_mask(mpc, 0x2, mpcc_id);
-	if (is_12bits_color_channel)
-		mpc32_set3dlut_ram12(mpc, lut1, lut_size, mpcc_id);
-	else
-		mpc32_set3dlut_ram10(mpc, lut1, lut_size, mpcc_id);
-
-	mpc32_select_3dlut_ram_mask(mpc, 0x4, mpcc_id);
-	if (is_12bits_color_channel)
-		mpc32_set3dlut_ram12(mpc, lut2, lut_size, mpcc_id);
-	else
-		mpc32_set3dlut_ram10(mpc, lut2, lut_size, mpcc_id);
-
-	mpc32_select_3dlut_ram_mask(mpc, 0x8, mpcc_id);
-	if (is_12bits_color_channel)
-		mpc32_set3dlut_ram12(mpc, lut3, lut_size, mpcc_id);
-	else
-		mpc32_set3dlut_ram10(mpc, lut3, lut_size, mpcc_id);
-
-	mpc32_set_3dlut_mode(mpc, mode, is_12bits_color_channel,
-		is_17x17x17, mpcc_id);
-
-	if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
-		mpc32_power_on_shaper_3dlut(mpc, mpcc_id, false);
-
-	return true;
+	return size;
 }
 
-void mpc60_program_lut_read_write_control(struct mpc *mpc, const enum MCM_LUT_ID id, bool lut_bank_a, int mpcc_id)
+static void mpc60_program_lut_mode(
+		struct mpc *mpc,
+		const enum MCM_LUT_ID id,
+		const bool enable,
+		const bool lut_bank_a,
+		const enum dc_cm_lut_size size,
+		const int mpcc_id)
 {
+	uint32_t lut_size;
+	struct dcn60_mpc *mpc60 = TO_DCN60_MPC(mpc);
 
 	switch (id) {
 	case MCM_LUT_3DLUT:
-		mpc32_select_3dlut_ram_mask(mpc, 0xf, mpcc_id);
+		if (enable) {
+			lut_size = mpc60_cm_lut_size_to_3dlut_size(size);
+			REG_UPDATE_2(MPCC_MCM_3DLUT_MODE[mpcc_id],
+					MPCC_MCM_3DLUT_MODE, 1,
+					MPCC_MCM_3DLUT_SIZE, lut_size);
+		} else {
+			if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
+				mpc32_power_on_shaper_3dlut(mpc, mpcc_id, false);
+			REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_MODE, 0);
+		}
 		break;
 	case MCM_LUT_SHAPER:
-		mpc32_configure_shaper_lut(mpc, lut_bank_a, mpcc_id);
+		if (enable) {
+			REG_UPDATE(MPCC_MCM_SHAPER_CONTROL[mpcc_id], MPCC_MCM_SHAPER_LUT_MODE, lut_bank_a ? 1 : 2);
+		} else {
+			if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
+				mpc32_power_on_shaper_3dlut(mpc, mpcc_id, false);
+			REG_UPDATE(MPCC_MCM_SHAPER_CONTROL[mpcc_id], MPCC_MCM_SHAPER_LUT_MODE, 0);
+		}
 		break;
 	case MCM_LUT_1DLUT:
-		mpc32_configure_post1dlut(mpc, lut_bank_a, mpcc_id);
+		if (enable) {
+			REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
+					MPCC_MCM_1DLUT_MODE, 2);
+		} else {
+			if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
+				mpc32_power_on_blnd_lut(mpc, mpcc_id, false);
+			REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
+					MPCC_MCM_1DLUT_MODE, 0);
+		}
+		REG_UPDATE(MPCC_MCM_1DLUT_CONTROL[mpcc_id],
+				MPCC_MCM_1DLUT_SELECT, lut_bank_a ? 0 : 1);
 		break;
 	}
 }
 
+static bool mpc60_program_3dlut(
+	struct mpc *mpc,
+	const struct tetrahedral_params *params,
+	int mpcc_id)
+{
+	union mcm_lut_params lut_params = { 0 };
+	lut_params.lut3d = params;
+
+	mpc60_program_lut_read_write_control(mpc,
+			MCM_LUT_3DLUT,
+			true,
+			params->use_12bits ? 12 : 10,
+			mpcc_id);
+	mpc401_populate_lut(mpc, MCM_LUT_3DLUT, &lut_params, true, mpcc_id);
+	mpc60_program_lut_mode(mpc,
+		MCM_LUT_3DLUT,
+		true,
+		true,
+		params->use_tetrahedral_9 ? CM_LUT_SIZE_999 : CM_LUT_SIZE_171717,
+		mpcc_id);
+
+	return true;
+}
+
 static const struct mpc_funcs dcn60_mpc_funcs = {
 	.read_mpcc_state = mpc1_read_mpcc_state,
 	.insert_plane = mpc60_insert_plane,
@@ -328,15 +286,8 @@ static const struct mpc_funcs dcn60_mpc_funcs = {
 	.get_3dlut_fast_load_status = mpc401_get_3dlut_fast_load_status,
 	.populate_lut = mpc401_populate_lut,
 	.program_lut_read_write_control = mpc60_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,
-	},
+	.program_lut_mode = mpc60_program_lut_mode,
+	.get_lut_mode = mpc401_get_lut_mode,
 	.rmcm = {
 		.enable_3dlut_fl = mpc42_enable_3dlut_fl,
 		.update_3dlut_fast_load_select = mpc42_update_3dlut_fast_load_select,
@@ -345,9 +296,9 @@ static const struct mpc_funcs dcn60_mpc_funcs = {
 		.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,
+		.get_3dlut_mode = mpc42_get_rmcm_3dlut_mode,
 	},
 };
 
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.h b/drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.h
index 76d5c721f742..640a322d15c1 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.h
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.h
@@ -469,19 +469,4 @@ void mpc60_program_rmcm_lut_read_write_control(struct mpc *mpc,
 	bool lut_bank_a,
 	bool enabled,
 	int mpcc_id);
-
-void mpc60_select_3dlut_ram(struct mpc *mpc,
-	enum dc_lut_mode mode,
-	bool is_color_channel_12bits,
-	uint32_t mpcc_id);
-
-bool mpc60_program_3dlut(struct mpc *mpc,
-	const struct tetrahedral_params *params,
-	int mpcc_id);
-
-void mpc60_program_lut_read_write_control(struct mpc *mpc,
-	const enum MCM_LUT_ID id,
-	bool lut_bank_a,
-	int mpcc_id);
-
 #endif /* DCN60_MPC_H_ */
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
index 6296330e2450..6370d3903eb5 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
@@ -704,6 +704,7 @@ static const struct resource_caps res_cap_dcn42 = {
 	.num_vmid = 16,
 	.num_mpc_3dlut = 2,
 	.num_dsc = 4,
+	.num_rmcm = 2,
 };
 
 static const struct dc_plane_cap plane_cap = {
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c
index b441d6d2d36b..4b7668abf4dc 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c
@@ -584,6 +584,7 @@ static const struct resource_caps res_cap_dcn6_0 = {
 	.num_mpc_3dlut = 4,
 	.num_dsc = 4,
 	.num_aux = 4,
+	.num_rmcm = 2,
 };
 
 static const struct dc_plane_cap plane_cap = {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* [PATCH 41/41] drm/amd/display: Promote DC to 3.2.392
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (37 preceding siblings ...)
  2026-07-31 21:13 ` [PATCH 40/41] drm/amd/display: Migrate color manager HW and fix MCM blend LUT issues Roman.Li
@ 2026-07-31 21:13 ` Roman.Li
  2026-08-04 13:24 ` [PATCH 00/41] DC Patches July 31, 2026 Wheeler, Daniel
  39 siblings, 0 replies; 43+ messages in thread
From: Roman.Li @ 2026-07-31 21:13 UTC (permalink / raw)
  To: amd-gfx
  Cc: Harry Wentland, Leo Li, Aurabindo Pillai, Roman Li, Wayne Lin,
	Tom Chung, Fangzhi Zuo, Dan Wheeler, Ray Wu, Ivan Lipski,
	Alex Hung, James Lin, Chenyu Chen, Taimur Hassan

From: Taimur Hassan <Syed.Hassan@amd.com>

This version brings along the following updates:

 - Add KUnit tests for crtc functions.
 - Add KUnit tests for crtc functions.
 - Add support for dynamic FFE levels.
 - Configure all CRC engines in pipe CRC source path.
 - Enable DCN6 compilation.
 - Fix ABM over VABC.
 - Fix CRC engine 1 enable/disable on DCN3.1.2+.
 - Fix MCM blend LUT issues.
 - Fix seamless mode switch not triggering for HDR to SDR transition.
 - Fix wb_info leak and NULL deref in writeback.
 - Increase fclk change latency on dcn351.
 - Refactor stream validation.
 - Resize MST HDCP per-connector arrays to 32.
 - Unify force_yuv debugfs into force_yuv_pixel_format.
 - Update VRR info packet to support 12-bit refresh rates.

Signed-off-by: Taimur Hassan <Syed.Hassan@amd.com>
Signed-off-by: Roman Li <roman.li@amd.com>
---
 drivers/gpu/drm/amd/display/dc/dc.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index b2fd3a94f067..705c500ad711 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -66,7 +66,7 @@ struct dcn_dsc_reg_state;
 struct dcn_optc_reg_state;
 struct dcn_dccg_reg_state;
 
-#define DC_VER "3.2.391"
+#define DC_VER "3.2.392"
 
 /**
  * MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 43+ messages in thread

* RE: [PATCH 00/41] DC Patches July 31, 2026
  2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
                   ` (38 preceding siblings ...)
  2026-07-31 21:13 ` [PATCH 41/41] drm/amd/display: Promote DC to 3.2.392 Roman.Li
@ 2026-08-04 13:24 ` Wheeler, Daniel
  2026-08-04 21:15   ` Timur Kristóf
  39 siblings, 1 reply; 43+ messages in thread
From: Wheeler, Daniel @ 2026-08-04 13:24 UTC (permalink / raw)
  To: Li, Roman, amd-gfx@lists.freedesktop.org
  Cc: Wentland, Harry, Li, Sun peng (Leo), Pillai, Aurabindo, Li, Roman,
	Lin, Wayne, Chung, ChiaHsuan (Tom), Zuo, Jerry, Wu, Ray,
	LIPSKI, IVAN, Hung, Alex, Lin, Ping Lei, Chen, Chen-Yu, Li, Roman

Public

Hi all,

This week this patchset was tested on 4 systems, two dGPU and two APU based, and tested across multiple display and connection types.

APU
        * Single Display eDP -> 1080p 60hz, 1920x1200 165hz, 3840x2400 60hz
        * Single Display DP (SST DSC) -> 4k144hz, 4k240hz
        * Multi display -> eDP + DP/HDMI/USB-C -> 1080p 60hz eDP + 4k 144hz, 4k 240hz (Includes USB-C to DP/HDMI adapters)
        * Thunderbolt -> LG Ultrafine 5k
        * MST DSC -> Cable Matters 101075 (DP to 3x DP) with 3x 4k60hz displays, HP Hook G2 with 2x 4k60hz displays
        * USB 4 -> HP Hook G4, Lenovo Thunderbolt Dock, both with 2x 4k60hz DP and 1x 4k60hz HDMI displays
        * SST PCON -> Club3D CAC-1085 + 1x 4k 144hz, FRL3, at a max resolution supported by the dongle of 4k 120hz YUV420 12bpc.
        * MST PCON -> 1x 4k 144hz, FRL3, at a max resolution supported by the adapter of 4k 120hz RGB 8bpc.

DGPU
        * Single Display DP (SST DSC) -> 4k144hz, 4k240hz
        * Multiple Display DP -> 4k240hz + 4k144hz
        * MST (Startech MST14DP123DP [DP to 3x DP] and 2x 4k 60hz displays)
        * MST DSC (with Cable Matters 101075 [DP to 3x DP] with 3x 4k60hz displays)

The testing is a mix of automated and manual tests. Manual testing includes (but is not limited to)
        * Changing display configurations and settings
        * Video/Audio playback
        * Benchmark testing
        * Suspend/Resume testing
        * Feature testing (Freesync, HDCP, etc.)

Automated testing includes (but is not limited to)
        * Script testing (scripts to automate some of the manual checks)
        * IGT testing

The testing is mainly tested on the following displays, but occasionally there are tests with other displays
        * Samsung G8 Neo 4k240hz
        * Samsung QN55QN95B 4k 120hz
        * Acer XV322QKKV 4k144hz
        * HP U27 4k Wireless 4k60hz
        * LG 27UD58B 4k60hz
        * LG 32UN650WA 4k60hz
        * LG Ultrafine 5k 5k60hz
        * AU Optronics B140HAN01.1 1080p 60hz eDP
        * AU Optronics B160UAN01.J 1920x1200 165hz eDP
        * Samsung ATNA60YV02-0 3840x2400 60Hz OLED eDP


The patchset consists of the amd-staging-drm-next branch (Head commit - 76e667ef60446d435b869360961888cca1500cb6 -> drm/amd/display: use proper context for logging) with new patches added on top of it.

Tested on Ubuntu 26.04.1, on Gnome Wayland.

Tested-by: Dan Wheeler <daniel.wheeler@amd.com>

Thank you,

Dan Wheeler
Sr. Technologist | AMD
SW Display
------------------------------------------------------------------------------------------------------------------
1 Commerce Valley Dr E, Thornhill, ON L3T 7X6
amd.com


-----Original Message-----
From: Roman.Li@amd.com <Roman.Li@amd.com>
Sent: Friday, July 31, 2026 5:12 PM
To: amd-gfx@lists.freedesktop.org
Cc: Wentland, Harry <Harry.Wentland@amd.com>; Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Pillai, Aurabindo <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Lin, Wayne <Wayne.Lin@amd.com>; Chung, ChiaHsuan (Tom) <ChiaHsuan.Chung@amd.com>; Zuo, Jerry <Jerry.Zuo@amd.com>; Wheeler, Daniel <Daniel.Wheeler@amd.com>; Wu, Ray <Ray.Wu@amd.com>; LIPSKI, IVAN <IVAN.LIPSKI@amd.com>; Hung, Alex <Alex.Hung@amd.com>; Lin, Ping Lei <PingLei.Lin@amd.com>; Chen, Chen-Yu <Chen-Yu.Chen@amd.com>; Li, Roman <Roman.Li@amd.com>
Subject: [PATCH 00/41] DC Patches July 31, 2026

From: Roman Li <Roman.Li@amd.com>

This DC patchset brings improvements in multiple areas. In summary, we highlight:
 - Add KUnit tests for crtc functions
 - Enable DCN6
 - Fix ABM, CRC engine, MCM, writeback issues
 - Refactor stream validation.

Cc: Dan Wheeler <daniel.wheeler@amd.com>

Alex Hung (2):
  drm/amd/display: Fix wb_info leak and NULL deref in writeback
  drm/amd/display: Fix more KUnit connector use-after-free bugs

Alvin Lee (1):
  drm/amd/display: Update BW bounding box unconditionally for DCN6

Aurabindo Pillai (5):
  drm/amd: Add DCN6 register headers
  drm/amd/display: Add new sources for DCN6
  drm/amd/display: Enable DCN6 init
  drm/amd/display: Dependent changes for DCN6
  drm/amd/display: Enable DCN6 sources compilation

Bhawanpreet Lakha (12):
  drm/amd/display: Add KUnit tests for more crtc functions
  drm/amd/display: Add vblank handling tests for crtc
  drm/amd/display: Add idle worker tests for crtc
  drm/amd/display: Add active plane count tests for crtc
  drm/amd/display: Add KUnit test for crtc vblank event completion
  drm/amd/display: Add KUnit tests for crtc set_vupdate_irq
  drm/amd/display: Add KUnit tests for crtc set_static_screen_optimze
  drm/amd/display: Add KUnit tests for crtc set_vblank
  drm/amd/display: Cover crtc set_vblank workqueue branch
  drm/amd/display: Cover crtc vblank IPS self-refresh restore
  drm/amd/display: Cover crtc vblank restore replay-supported path
  drm/amd/display: Cover crtc destroy_state stream release

Charlene Liu (1):
  drm/amd/display: Ensure dtbclk is enabled

Fangzhi Zuo (1):
  drm/amd/display: Gate HDMI FRL status polling on active FRL link rate

Harry VanZyllDeJong (1):
  drm/amd/display: Update VRR info packet to support 12-bit refresh
    rates

Harry Wentland (2):
  drm/amd/display: Resize MST HDCP per-connector arrays to 32
  drm/amd/display: Bounds-check connector->index in dm_dp_mst_get_modes

Iswara Nagulendran (1):
  drm/amd/display: Fix ABM over VABC

Ivan Lipski (3):
  drm/amd/display: Refactor stream validation
  drm/amd/display: Unify force_yuv debugfs into force_yuv_pixel_format
  drm/amd/display: Align connector KUnit tests with stream validation
    refactor

Karthi Kandasamy (1):
  drm/amd/display: Fix seamless mode switch not triggering for HDR to
    SDR transition

Matthew Stewart (1):
  drm/amd/display: Add missing DCN42B register defines

Rafal Ostrowski (1):
  drm/amd/display: Migrate color manager HW and fix MCM blend LUT issues

Relja Vojvodic (2):
  drm/amd/display: switch max FFE level cap based on FRL link rate
  drm/amd/display: Add FFE level defaults

Roman Li (1):
  drm/amd/display: Remove duplicate in tests/Makefile

Sung-huai Wang (1):
  drm/amd/display: Increase fclk change latency on dcn351

Taimur Hassan (2):
  drm/amd/display: Add missing DMUB CACP and PR definitions
  drm/amd/display: Promote DC to 3.2.392

Wayne Lin (3):
  drm/amd/display: Add missing OTG_CRC1_SELECT mask for DCN3.2
  drm/amd/display: Fix CRC engine 1 enable/disable on DCN3.1.2+
  drm/amd/display: Configure all CRC engines in pipe CRC source path

 drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c |     1 +
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |    31 +-
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |     2 -
 .../amd/display/amdgpu_dm/amdgpu_dm_audio.h   |     2 +-
 .../display/amdgpu_dm/amdgpu_dm_connector.c   |   289 +-
 .../display/amdgpu_dm/amdgpu_dm_connector.h   |     8 +-
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c |    13 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |    25 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_crtc.h    |     9 +
 .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c |    57 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_dmub.c    |    10 +
 .../amd/display/amdgpu_dm/amdgpu_dm_dmub.h    |     1 +
 .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c    |    10 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.h    |    10 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |     6 +
 .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |     3 +-
 .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |     9 +-
 .../drm/amd/display/amdgpu_dm/tests/Makefile  |     1 -
 .../tests/amdgpu_dm_connector_test.c          |   163 +-
 .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     |  1436 +
 .../amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c |    29 +
 .../tests/amdgpu_dm_kunit_test_helpers.h      |     3 +
 .../display/dc/bios/command_table_helper2.c   |     1 +
 .../gpu/drm/amd/display/dc/clk_mgr/Makefile   |     9 +
 .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c  |    15 +
 .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c  |    28 +-
 .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h  |     1 +
 .../drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h |   389 +
 .../display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c  |  1673 +
 .../display/dc/clk_mgr/dcn60/dcn60_clk_mgr.h  |   150 +
 .../dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.c  |   369 +
 .../dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.h  |    35 +
 drivers/gpu/drm/amd/display/dc/core/dc.c      |    76 +-
 .../drm/amd/display/dc/core/dc_hw_sequencer.c |   428 +
 .../gpu/drm/amd/display/dc/core/dc_resource.c |    47 +
 .../gpu/drm/amd/display/dc/core/dc_state.c    |    12 +
 .../gpu/drm/amd/display/dc/core/dc_stream.c   |    27 +-
 drivers/gpu/drm/amd/display/dc/dc.h           |    41 +-
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c  |    44 +
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h  |    23 +
 drivers/gpu/drm/amd/display/dc/dc_helper.c    |     2 +
 drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |    53 +-
 .../gpu/drm/amd/display/dc/dc_spl_translate.c |    32 +-
 .../gpu/drm/amd/display/dc/dc_state_priv.h    |     1 +
 drivers/gpu/drm/amd/display/dc/dc_stream.h    |     5 +
 drivers/gpu/drm/amd/display/dc/dc_types.h     |    13 +-
 drivers/gpu/drm/amd/display/dc/dccg/Makefile  |     8 +
 .../amd/display/dc/dccg/dcn20/dcn20_dccg.h    |    10 +
 .../amd/display/dc/dccg/dcn60/dcn60_dccg.c    |   187 +
 .../amd/display/dc/dccg/dcn60/dcn60_dccg.h    |   182 +
 .../drm/amd/display/dc/dce/dce_clock_source.c |    28 +
 .../drm/amd/display/dc/dce/dce_clock_source.h |     9 +
 drivers/gpu/drm/amd/display/dc/dio/Makefile   |     8 +
 .../display/dc/dio/dcn10/dcn10_link_encoder.h |    16 +
 .../dc/dio/dcn401/dcn401_dio_link_encoder.c   |    15 +
 .../dc/dio/dcn401/dcn401_dio_link_encoder.h   |    10 +
 .../dc/dio/dcn60/dcn60_dio_link_encoder.c     |   373 +
 .../dc/dio/dcn60/dcn60_dio_link_encoder.h     |    43 +
 .../dc/dio/dcn60/dcn60_dio_stream_encoder.c   |   538 +
 .../dc/dio/dcn60/dcn60_dio_stream_encoder.h   |   181 +
 drivers/gpu/drm/amd/display/dc/dm_helpers.h   |     8 +
 .../amd/display/dc/dml/dcn351/dcn351_fpu.c    |     4 +-
 .../gpu/drm/amd/display/dc/dml2_0/Makefile    |    25 +
 .../dml2_0/dml21/dml21_translation_helper.c   |    57 +-
 .../amd/display/dc/dml2_0/dml21/dml21_utils.c |   129 +-
 .../dml21/inc/bounding_boxes/dcn5_soc_bb.h    |    36 +
 .../dml21/inc/bounding_boxes/dcn6_soc_bb.h    |   229 +
 .../bounding_boxes/utm_qos_model_dchub_v1.h   |   109 +
 .../bounding_boxes/utm_qos_model_dchub_v2.h   |   122 +
 .../bounding_boxes/utm_qos_model_dchub_v3.h   |    53 +
 .../inc/bounding_boxes/utm_qos_model_types.h  |    51 +
 .../dc/dml2_0/dml21/inc/dml_dmub_cmd.h        |   502 +
 .../dml21/inc/dml_top_display_cfg_types.h     |    10 +
 .../dml21/inc/dml_top_soc_parameter_types.h   |     2 +
 .../dc/dml2_0/dml21/inc/dml_top_types.h       |    45 +
 .../dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.c |   152 +
 .../dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.h |     9 +
 .../dml21/src/dml2_cga/dml2_cga_factory.c     |    38 +
 .../dml21/src/dml2_cga/dml2_cga_factory.h     |     9 +
 .../dml2_core_calcs_dsc_shared_types.h        |    32 +
 .../src/dml2_core/dml2_core_dcn4_calcs.c      |     1 +
 .../dml2_core/dml2_core_dcn5_calcs_dchub.c    |  5893 ++
 .../dml2_core/dml2_core_dcn5_calcs_dchub.h    |   426 +
 .../dml2_core_dcn5_calcs_display_pipe.c       |  1029 +
 .../dml2_core_dcn5_calcs_display_pipe.h       |   151 +
 .../dml2_core_dcn5_calcs_dsc_latency.c        |   501 +
 .../dml2_core_dcn5_calcs_dsc_latency.h        |    23 +
 .../dml2_core_dcn5_funcs_initialize.c         |    78 +
 .../dml2_core_dcn5_funcs_initialize.h         |    12 +
 .../dml2_core_dcn5_funcs_mode_programming.c   |  1791 +
 .../dml2_core_dcn5_funcs_mode_programming.h   |    11 +
 .../dml2_core_dcn5_funcs_mode_support.c       |  2957 +
 .../dml2_core_dcn5_funcs_mode_support.h       |    11 +
 .../src/dml2_core/dml2_core_dcn6_calcs.c      |    11 +
 .../src/dml2_core/dml2_core_dcn6_calcs.h      |     8 +
 .../dml2_core/dml2_core_dcn6_calcs_dchub.c    |  1951 +
 .../dml2_core/dml2_core_dcn6_calcs_dchub.h    |   101 +
 .../dml2_core_dcn6_funcs_initialize.c         |   165 +
 .../dml2_core_dcn6_funcs_initialize.h         |    12 +
 .../dml2_core_dcn6_funcs_mode_programming.c   |  1389 +
 .../dml2_core_dcn6_funcs_mode_programming.h   |    11 +
 .../dml2_core_dcn6_funcs_mode_support.c       |  4277 ++
 .../dml2_core_dcn6_funcs_mode_support.h       |    11 +
 .../dml21/src/dml2_core/dml2_core_factory.c   |    25 +
 .../src/dml2_core/dml2_core_shared_types.h    |   160 +
 .../dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c      |     1 -
 .../dml21/src/dml2_dpmm/dml2_dpmm_dcn5.c      |   449 +
 .../dml21/src/dml2_dpmm/dml2_dpmm_dcn5.h      |    19 +
 .../dml21/src/dml2_dpmm/dml2_dpmm_factory.c   |    12 +
 .../dml21/src/dml2_mcg/dml2_mcg_factory.c     |     5 +
 .../dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c  |    57 +
 .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.c |   522 +
 .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.h |    21 +
 .../dml2_pmo/dml2_pmo_dcn5_stage_optimizers.c |  2228 +
 .../dml2_pmo/dml2_pmo_dcn5_stage_optimizers.h |    97 +
 .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.c |   506 +
 .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.h |    22 +
 .../dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c |  1789 +
 .../dml2_pmo/dml2_pmo_dcn6_stage_optimizers.h |    17 +
 .../dml21/src/dml2_pmo/dml2_pmo_factory.c     |    34 +
 .../alternate_pstate_shared_lib.c             |  1078 +
 .../alternate_pstate_shared_lib.h             |   109 +
 .../dml21/src/dml2_top/dml2_top_interfaces.c  |     7 +
 .../dml2_0/dml21/src/dml2_top/dml2_top_utm.c  |   394 +
 .../dml2_0/dml21/src/dml2_top/dml2_top_utm.h  |     9 +
 .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.c    |   144 +
 .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.h    |    11 +
 .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c    |   405 +
 .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.h    |    12 +
 .../dml2_utm_soc_bb/dml2_utm_soc_bb_factory.c |    29 +
 .../dml2_utm_soc_bb/dml2_utm_soc_bb_factory.h |    11 +
 .../src/inc/dml2_internal_shared_types.h      |   485 +
 .../drm/amd/display/dc/dml2_0/dml2_wrapper.h  |     8 +
 drivers/gpu/drm/amd/display/dc/dpp/Makefile   |    17 +
 .../amd/display/dc/dpp/dcn401/dcn401_dpp.h    |    41 +
 .../display/dc/dpp/dcn401/dcn401_dpp_dscl.c   |    26 +-
 .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c  |     7 +-
 .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h  |     6 +
 .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c  |   391 +
 .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h  |    86 +
 .../drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c  |   346 +
 .../drm/amd/display/dc/dpp/dcn60/dcn60_dpp.h  |   525 +
 .../amd/display/dc/dpp/dcn60/dcn60_dpp_dscl.c |   315 +
 drivers/gpu/drm/amd/display/dc/dsc/Makefile   |     7 +
 .../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c  |   447 +
 .../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h  |   248 +
 drivers/gpu/drm/amd/display/dc/gpio/Makefile  |    10 +
 .../display/dc/gpio/dcn60/hw_factory_dcn60.c  |   228 +
 .../display/dc/gpio/dcn60/hw_factory_dcn60.h  |    11 +
 .../dc/gpio/dcn60/hw_translate_dcn60.c        |   168 +
 .../dc/gpio/dcn60/hw_translate_dcn60.h        |    13 +
 .../gpu/drm/amd/display/dc/gpio/ddc_regs.h    |    15 +
 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c  |   302 +
 drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h  |    28 +
 .../gpu/drm/amd/display/dc/gpio/hw_factory.c  |     4 +
 .../drm/amd/display/dc/gpio/hw_translate.c    |     4 +
 .../gpu/drm/amd/display/dc/hdcp/hdcp_msg.c    |     9 +
 drivers/gpu/drm/amd/display/dc/hpo/Makefile   |     8 +
 .../hpo/dcn31/dcn31_hpo_dp_stream_encoder.h   |    47 -
 .../dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.c |   114 +
 .../dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.h |    18 +
 .../hpo/dcn60/dcn60_hpo_frl_stream_encoder.c  |   358 +
 .../hpo/dcn60/dcn60_hpo_frl_stream_encoder.h  |    32 +
 .../gpu/drm/amd/display/dc/hubbub/Makefile    |     8 +
 .../display/dc/hubbub/dcn10/dcn10_hubbub.h    |   108 +
 .../display/dc/hubbub/dcn60/dcn60_hubbub.c    |  1816 +
 .../display/dc/hubbub/dcn60/dcn60_hubbub.h    |   207 +
 drivers/gpu/drm/amd/display/dc/hubp/Makefile  |    16 +
 .../amd/display/dc/hubp/dcn20/dcn20_hubp.h    |    29 +
 .../amd/display/dc/hubp/dcn401/dcn401_hubp.c  |   201 +-
 .../amd/display/dc/hubp/dcn401/dcn401_hubp.h  |    23 +-
 .../amd/display/dc/hubp/dcn42/dcn42_hubp.c    |    78 +-
 .../amd/display/dc/hubp/dcn42/dcn42_hubp.h    |    10 +-
 .../amd/display/dc/hubp/dcn50/dcn50_hubp.c    |   532 +
 .../amd/display/dc/hubp/dcn50/dcn50_hubp.h    |    48 +
 .../amd/display/dc/hubp/dcn60/dcn60_hubp.c    |   472 +
 .../amd/display/dc/hubp/dcn60/dcn60_hubp.h    |   272 +
 drivers/gpu/drm/amd/display/dc/hwss/Makefile  |    16 +
 .../drm/amd/display/dc/hwss/dce/dce_hwseq.h   |     9 +
 .../amd/display/dc/hwss/dce110/dce110_hwseq.c |    21 +-
 .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c   |     3 +-
 .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c   |     3 +-
 .../amd/display/dc/hwss/dcn30/dcn30_hwseq.c   |     3 +-
 .../amd/display/dc/hwss/dcn31/dcn31_hwseq.c   |    21 +-
 .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c   |     5 +-
 .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c   |     8 +-
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c |   483 +-
 .../amd/display/dc/hwss/dcn401/dcn401_hwseq.h |     7 +-
 .../amd/display/dc/hwss/dcn401/dcn401_init.c  |     1 -
 .../amd/display/dc/hwss/dcn42/dcn42_hwseq.c   |   488 +-
 .../amd/display/dc/hwss/dcn42/dcn42_hwseq.h   |     6 -
 .../amd/display/dc/hwss/dcn42/dcn42_init.c    |     2 -
 .../amd/display/dc/hwss/dcn50/dcn50_hwseq.c   |   759 +
 .../amd/display/dc/hwss/dcn50/dcn50_hwseq.h   |    32 +
 .../amd/display/dc/hwss/dcn60/dcn60_hwseq.c   |  1164 +
 .../amd/display/dc/hwss/dcn60/dcn60_hwseq.h   |    32 +
 .../amd/display/dc/hwss/dcn60/dcn60_init.c    |   181 +
 .../amd/display/dc/hwss/dcn60/dcn60_init.h    |    12 +
 .../drm/amd/display/dc/hwss/hw_sequencer.h    |    19 +-
 .../display/dc/hwss/hw_sequencer_private.h    |     5 -
 .../gpu/drm/amd/display/dc/inc/core_types.h   |     1 +
 .../gpu/drm/amd/display/dc/inc/hw/clk_mgr.h   |     1 +
 .../amd/display/dc/inc/hw/clk_mgr_internal.h  |    22 +
 .../amd/display/dc/inc/hw/cursor_reg_cache.h  |     3 +-
 drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h   |     7 +
 drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h  |    35 +-
 .../drm/amd/display/dc/inc/hw/link_encoder.h  |     6 +
 drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h   |    81 +-
 .../gpu/drm/amd/display/dc/inc/hw/transform.h |     1 +
 drivers/gpu/drm/amd/display/dc/inc/resource.h |     2 +
 drivers/gpu/drm/amd/display/dc/irq/Makefile   |     9 +
 .../display/dc/irq/dcn60/irq_service_dcn60.c  |   417 +
 .../display/dc/irq/dcn60/irq_service_dcn60.h  |    12 +
 .../drm/amd/display/dc/link/link_detection.c  |    29 +
 .../drm/amd/display/dc/link/link_factory.c    |     5 +
 .../amd/display/dc/link/protocols/link_ddc.c  |     8 +
 .../display/dc/link/protocols/link_hdmi_frl.c |    23 +-
 drivers/gpu/drm/amd/display/dc/mpc/Makefile   |     8 +
 .../amd/display/dc/mpc/dcn401/dcn401_mpc.c    |   177 +-
 .../amd/display/dc/mpc/dcn401/dcn401_mpc.h    |    25 +-
 .../drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c  |   405 +-
 .../drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h  |    55 +-
 .../drm/amd/display/dc/mpc/dcn60/dcn60_mpc.c  |   330 +
 .../drm/amd/display/dc/mpc/dcn60/dcn60_mpc.h  |   472 +
 drivers/gpu/drm/amd/display/dc/opp/Makefile   |     8 +
 .../drm/amd/display/dc/opp/dcn60/dcn60_opp.c  |    25 +
 .../drm/amd/display/dc/opp/dcn60/dcn60_opp.h  |    64 +
 drivers/gpu/drm/amd/display/dc/optc/Makefile  |     9 +
 .../amd/display/dc/optc/dcn10/dcn10_optc.c    |    36 +-
 .../amd/display/dc/optc/dcn10/dcn10_optc.h    |     3 +-
 .../amd/display/dc/optc/dcn31/dcn31_optc.h    |     4 +
 .../amd/display/dc/optc/dcn314/dcn314_optc.h  |     1 +
 .../amd/display/dc/optc/dcn32/dcn32_optc.h    |     2 +
 .../amd/display/dc/optc/dcn35/dcn35_optc.c    |    26 +-
 .../amd/display/dc/optc/dcn401/dcn401_optc.h  |     1 +
 .../amd/display/dc/optc/dcn42/dcn42_optc.c    |     9 +-
 .../amd/display/dc/optc/dcn42/dcn42_optc.h    |     4 +
 .../amd/display/dc/optc/dcn60/dcn60_optc.c    |   107 +
 .../amd/display/dc/optc/dcn60/dcn60_optc.h    |   178 +
 .../gpu/drm/amd/display/dc/resource/Makefile  |    10 +
 .../dc/resource/dcn10/dcn10_resource.c        |     1 +
 .../dc/resource/dcn20/dcn20_resource.c        |     1 +
 .../dc/resource/dcn201/dcn201_resource.c      |     1 +
 .../dc/resource/dcn21/dcn21_resource.c        |     1 +
 .../dc/resource/dcn30/dcn30_resource.c        |     2 +
 .../dc/resource/dcn301/dcn301_resource.c      |     1 +
 .../dc/resource/dcn302/dcn302_resource.c      |     2 +
 .../dc/resource/dcn303/dcn303_resource.c      |     2 +
 .../dc/resource/dcn31/dcn31_resource.c        |     1 +
 .../dc/resource/dcn314/dcn314_resource.c      |     2 +
 .../dc/resource/dcn315/dcn315_resource.c      |     6 +-
 .../dc/resource/dcn316/dcn316_resource.c      |     5 +-
 .../dc/resource/dcn32/dcn32_resource.c        |     2 +
 .../dc/resource/dcn321/dcn321_resource.c      |     2 +
 .../dc/resource/dcn35/dcn35_resource.c        |     2 +
 .../dc/resource/dcn351/dcn351_resource.c      |     2 +
 .../dc/resource/dcn36/dcn36_resource.c        |     2 +
 .../dc/resource/dcn401/dcn401_resource.c      |    34 +-
 .../dc/resource/dcn401/dcn401_resource.h      |     4 +
 .../dc/resource/dcn42/dcn42_resource.c        |     3 +
 .../dc/resource/dcn42b/dcn42b_resource.c      |    20 +-
 .../dc/resource/dcn60/dcn60_resource.c        |  2377 +
 .../dc/resource/dcn60/dcn60_resource.h        |   676 +
 .../display/dc/soc_and_ip_translator/Makefile |     3 +
 .../dcn60/dcn60_soc_and_ip_translator.c       |   117 +
 .../dcn60/dcn60_soc_and_ip_translator.h       |    16 +
 .../soc_and_ip_translator.c                   |     4 +
 drivers/gpu/drm/amd/display/dmub/dmub_srv.h   |     5 +
 .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   |   229 +-
 drivers/gpu/drm/amd/display/dmub/src/Makefile |     1 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn60.c |   732 +
 .../gpu/drm/amd/display/dmub/src/dmub_dcn60.h |   303 +
 .../gpu/drm/amd/display/dmub/src/dmub_srv.c   |    52 +
 .../gpu/drm/amd/display/include/dal_asic_id.h |    18 +
 .../gpu/drm/amd/display/include/dal_types.h   |     1 +
 .../amd/display/modules/freesync/freesync.c   |     8 +-
 .../drm/amd/display/modules/power/power_abm.c |   215 +-
 .../amd/display/modules/power/power_helpers.h |     9 +
 .../drm/amd/display/modules/power/power_psr.c |     7 +
 .../amd/display/modules/power/power_replay.c  |     7 +
 .../include/asic_reg/dcn/dcn_6_0_0_offset.h   | 15799 +++++
 .../include/asic_reg/dcn/dcn_6_0_0_sh_mask.h  | 58556 ++++++++++++++++
 .../include/asic_reg/dpcs/dpcs_6_0_0_offset.h |    47 +
 .../asic_reg/dpcs/dpcs_6_0_0_sh_mask.h        |    55 +
 .../asic_reg/mmhub/mmhub_5_0_1_offset.h       |    17 +
 .../asic_reg/mmhub/mmhub_5_0_1_sh_mask.h      |    17 +
 286 files changed, 129427 insertions(+), 1800 deletions(-)  create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn5_soc_bb.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn6_soc_bb.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos_model_dchub_v1.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos_model_dchub_v2.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos_model_dchub_v3.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos_model_types.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_dmub_cmd.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_factory.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_factory.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_calcs_dsc_shared_types.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_dchub.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_dchub.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_display_pipe.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_display_pipe.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_dsc_latency.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_calcs_dsc_latency.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_initialize.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_initialize.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_programming.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_programming.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_support.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_funcs_mode_support.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_calcs.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_calcs.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_calcs_dchub.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_calcs_dchub.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_initialize.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_initialize.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_programming.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_programming.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_support.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_funcs_mode_support.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn5.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn5.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5_stage_optimizers.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5_stage_optimizers.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stage_optimizers.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/alternate_pstate_shared_lib.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_utm.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_utm.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_factory.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_soc_bb_factory.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp_dscl.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_factory_dcn60.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_factory_dcn60.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_translate_dcn60.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_translate_dcn60.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_stream_encoder.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_stream_encoder.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hubbub/dcn60/dcn60_hubbub.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hubbub/dcn60/dcn60_hubbub.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn50/dcn50_hubp.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn50/dcn50_hubp.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dcn60/irq_service_dcn60.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/irq/dcn60/irq_service_dcn60.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/opp/dcn60/dcn60_opp.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/opp/dcn60/dcn60_opp.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn60/dcn60_optc.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/optc/dcn60/dcn60_optc.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.h
 create mode 100644 drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn60/dcn60_soc_and_ip_translator.c
 create mode 100644 drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn60/dcn60_soc_and_ip_translator.h
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.c
 create mode 100644 drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.h
 create mode 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_6_0_0_offset.h
 create mode 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_6_0_0_sh_mask.h
 create mode 100644 drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_6_0_0_offset.h
 create mode 100644 drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_6_0_0_sh_mask.h
 create mode 100644 drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_5_0_1_offset.h
 create mode 100644 drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_5_0_1_sh_mask.h

--
2.34.1


^ permalink raw reply	[flat|nested] 43+ messages in thread

* Re: [PATCH 00/41] DC Patches July 31, 2026
  2026-08-04 13:24 ` [PATCH 00/41] DC Patches July 31, 2026 Wheeler, Daniel
@ 2026-08-04 21:15   ` Timur Kristóf
  2026-08-05 20:03     ` Wheeler, Daniel
  0 siblings, 1 reply; 43+ messages in thread
From: Timur Kristóf @ 2026-08-04 21:15 UTC (permalink / raw)
  To: Li, Roman, amd-gfx@lists.freedesktop.org
  Cc: Wentland, Harry, Li, Sun peng (Leo), Pillai, Aurabindo, Li, Roman,
	Lin, Wayne, Chung, ChiaHsuan (Tom), Zuo, Jerry, Wu, Ray,
	LIPSKI, IVAN, Hung, Alex, Lin, Ping Lei, Chen, Chen-Yu, Li, Roman,
	Wheeler, Daniel, Alex Deucher

On Tuesday, August 4, 2026 3:24:14 PM Central European Summer Time Wheeler, 
Daniel wrote:
> Public
> 
> Hi all,
> 
> This week this patchset was tested on 4 systems, two dGPU and two APU based,
> and tested across multiple display and connection types.

Hi Daniel,

Is there any way the community could contribute to help prevent regressions?

I respect that AMD wants to minimize time and resources spent on development 
for legacy GPUs, that is understandable and reasonable. However, could we 
please find a way to try to minimize regressions? For example, at the very 
least, would it be feasible to make sure that all supported GPUs can boot to a 
functional graphical desktop without crashing or showing a black screen?

Current amd-staging-drm-next is broken on all Vega and older GPUs since the 
20th July DC patch series. Basically the display driver just crashes on boot. 
I already sent fixes for two regressions, and we're still looking for one more.

Thanks & best regards,
Timur

> 
> APU
>         * Single Display eDP -> 1080p 60hz, 1920x1200 165hz, 3840x2400 60hz
>         * Single Display DP (SST DSC) -> 4k144hz, 4k240hz
>         * Multi display -> eDP + DP/HDMI/USB-C -> 1080p 60hz eDP + 4k 144hz,
> 4k 240hz (Includes USB-C to DP/HDMI adapters) * Thunderbolt -> LG Ultrafine
> 5k
>         * MST DSC -> Cable Matters 101075 (DP to 3x DP) with 3x 4k60hz
> displays, HP Hook G2 with 2x 4k60hz displays * USB 4 -> HP Hook G4, Lenovo
> Thunderbolt Dock, both with 2x 4k60hz DP and 1x 4k60hz HDMI displays * SST
> PCON -> Club3D CAC-1085 + 1x 4k 144hz, FRL3, at a max resolution supported
> by the dongle of 4k 120hz YUV420 12bpc. * MST PCON -> 1x 4k 144hz, FRL3, at
> a max resolution supported by the adapter of 4k 120hz RGB 8bpc.
> 
> DGPU
>         * Single Display DP (SST DSC) -> 4k144hz, 4k240hz
>         * Multiple Display DP -> 4k240hz + 4k144hz
>         * MST (Startech MST14DP123DP [DP to 3x DP] and 2x 4k 60hz displays)
>         * MST DSC (with Cable Matters 101075 [DP to 3x DP] with 3x 4k60hz
> displays)
> 
> The testing is a mix of automated and manual tests. Manual testing includes
> (but is not limited to) * Changing display configurations and settings
>         * Video/Audio playback
>         * Benchmark testing
>         * Suspend/Resume testing
>         * Feature testing (Freesync, HDCP, etc.)
> 
> Automated testing includes (but is not limited to)
>         * Script testing (scripts to automate some of the manual checks)
>         * IGT testing
> 
> The testing is mainly tested on the following displays, but occasionally
> there are tests with other displays * Samsung G8 Neo 4k240hz
>         * Samsung QN55QN95B 4k 120hz
>         * Acer XV322QKKV 4k144hz
>         * HP U27 4k Wireless 4k60hz
>         * LG 27UD58B 4k60hz
>         * LG 32UN650WA 4k60hz
>         * LG Ultrafine 5k 5k60hz
>         * AU Optronics B140HAN01.1 1080p 60hz eDP
>         * AU Optronics B160UAN01.J 1920x1200 165hz eDP
>         * Samsung ATNA60YV02-0 3840x2400 60Hz OLED eDP
> 
> 
> The patchset consists of the amd-staging-drm-next branch (Head commit -
> 76e667ef60446d435b869360961888cca1500cb6 -> drm/amd/display: use proper
> context for logging) with new patches added on top of it.
> 
> Tested on Ubuntu 26.04.1, on Gnome Wayland.
> 
> Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
> 
> Thank you,
> 
> Dan Wheeler
> Sr. Technologist | AMD
> SW Display
> ----------------------------------------------------------------------------
> -------------------------------------- 1 Commerce Valley Dr E, Thornhill, ON
> L3T 7X6
> amd.com
> 
> 
> -----Original Message-----
> From: Roman.Li@amd.com <Roman.Li@amd.com>
> Sent: Friday, July 31, 2026 5:12 PM
> To: amd-gfx@lists.freedesktop.org
> Cc: Wentland, Harry <Harry.Wentland@amd.com>; Li, Sun peng (Leo)
> <Sunpeng.Li@amd.com>; Pillai, Aurabindo <Aurabindo.Pillai@amd.com>; Li,
> Roman <Roman.Li@amd.com>; Lin, Wayne <Wayne.Lin@amd.com>; Chung, ChiaHsuan
> (Tom) <ChiaHsuan.Chung@amd.com>; Zuo, Jerry <Jerry.Zuo@amd.com>; Wheeler,
> Daniel <Daniel.Wheeler@amd.com>; Wu, Ray <Ray.Wu@amd.com>; LIPSKI, IVAN
> <IVAN.LIPSKI@amd.com>; Hung, Alex <Alex.Hung@amd.com>; Lin, Ping Lei
> <PingLei.Lin@amd.com>; Chen, Chen-Yu <Chen-Yu.Chen@amd.com>; Li, Roman
> <Roman.Li@amd.com> Subject: [PATCH 00/41] DC Patches July 31, 2026
> 
> From: Roman Li <Roman.Li@amd.com>
> 
> This DC patchset brings improvements in multiple areas. In summary, we
> highlight: - Add KUnit tests for crtc functions
>  - Enable DCN6
>  - Fix ABM, CRC engine, MCM, writeback issues
>  - Refactor stream validation.
> 
> Cc: Dan Wheeler <daniel.wheeler@amd.com>
> 
> Alex Hung (2):
>   drm/amd/display: Fix wb_info leak and NULL deref in writeback
>   drm/amd/display: Fix more KUnit connector use-after-free bugs
> 
> Alvin Lee (1):
>   drm/amd/display: Update BW bounding box unconditionally for DCN6
> 
> Aurabindo Pillai (5):
>   drm/amd: Add DCN6 register headers
>   drm/amd/display: Add new sources for DCN6
>   drm/amd/display: Enable DCN6 init
>   drm/amd/display: Dependent changes for DCN6
>   drm/amd/display: Enable DCN6 sources compilation
> 
> Bhawanpreet Lakha (12):
>   drm/amd/display: Add KUnit tests for more crtc functions
>   drm/amd/display: Add vblank handling tests for crtc
>   drm/amd/display: Add idle worker tests for crtc
>   drm/amd/display: Add active plane count tests for crtc
>   drm/amd/display: Add KUnit test for crtc vblank event completion
>   drm/amd/display: Add KUnit tests for crtc set_vupdate_irq
>   drm/amd/display: Add KUnit tests for crtc set_static_screen_optimze
>   drm/amd/display: Add KUnit tests for crtc set_vblank
>   drm/amd/display: Cover crtc set_vblank workqueue branch
>   drm/amd/display: Cover crtc vblank IPS self-refresh restore
>   drm/amd/display: Cover crtc vblank restore replay-supported path
>   drm/amd/display: Cover crtc destroy_state stream release
> 
> Charlene Liu (1):
>   drm/amd/display: Ensure dtbclk is enabled
> 
> Fangzhi Zuo (1):
>   drm/amd/display: Gate HDMI FRL status polling on active FRL link rate
> 
> Harry VanZyllDeJong (1):
>   drm/amd/display: Update VRR info packet to support 12-bit refresh
>     rates
> 
> Harry Wentland (2):
>   drm/amd/display: Resize MST HDCP per-connector arrays to 32
>   drm/amd/display: Bounds-check connector->index in dm_dp_mst_get_modes
> 
> Iswara Nagulendran (1):
>   drm/amd/display: Fix ABM over VABC
> 
> Ivan Lipski (3):
>   drm/amd/display: Refactor stream validation
>   drm/amd/display: Unify force_yuv debugfs into force_yuv_pixel_format
>   drm/amd/display: Align connector KUnit tests with stream validation
>     refactor
> 
> Karthi Kandasamy (1):
>   drm/amd/display: Fix seamless mode switch not triggering for HDR to
>     SDR transition
> 
> Matthew Stewart (1):
>   drm/amd/display: Add missing DCN42B register defines
> 
> Rafal Ostrowski (1):
>   drm/amd/display: Migrate color manager HW and fix MCM blend LUT issues
> 
> Relja Vojvodic (2):
>   drm/amd/display: switch max FFE level cap based on FRL link rate
>   drm/amd/display: Add FFE level defaults
> 
> Roman Li (1):
>   drm/amd/display: Remove duplicate in tests/Makefile
> 
> Sung-huai Wang (1):
>   drm/amd/display: Increase fclk change latency on dcn351
> 
> Taimur Hassan (2):
>   drm/amd/display: Add missing DMUB CACP and PR definitions
>   drm/amd/display: Promote DC to 3.2.392
> 
> Wayne Lin (3):
>   drm/amd/display: Add missing OTG_CRC1_SELECT mask for DCN3.2
>   drm/amd/display: Fix CRC engine 1 enable/disable on DCN3.1.2+
>   drm/amd/display: Configure all CRC engines in pipe CRC source path
> 
>  drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c |     1 +
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |    31 +-
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |     2 -
>  .../amd/display/amdgpu_dm/amdgpu_dm_audio.h   |     2 +-
>  .../display/amdgpu_dm/amdgpu_dm_connector.c   |   289 +-
>  .../display/amdgpu_dm/amdgpu_dm_connector.h   |     8 +-
>  .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c |    13 +-
>  .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |    25 +-
>  .../amd/display/amdgpu_dm/amdgpu_dm_crtc.h    |     9 +
>  .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c |    57 +-
>  .../amd/display/amdgpu_dm/amdgpu_dm_dmub.c    |    10 +
>  .../amd/display/amdgpu_dm/amdgpu_dm_dmub.h    |     1 +
>  .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c    |    10 +-
>  .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.h    |    10 +-
>  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |     6 +
>  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |     3 +-
>  .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |     9 +-
>  .../drm/amd/display/amdgpu_dm/tests/Makefile  |     1 -
>  .../tests/amdgpu_dm_connector_test.c          |   163 +-
>  .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     |  1436 +
>  .../amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c |    29 +
>  .../tests/amdgpu_dm_kunit_test_helpers.h      |     3 +
>  .../display/dc/bios/command_table_helper2.c   |     1 +
>  .../gpu/drm/amd/display/dc/clk_mgr/Makefile   |     9 +
>  .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c  |    15 +
>  .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c  |    28 +-
>  .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h  |     1 +
>  .../drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h |   389 +
>  .../display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c  |  1673 +
>  .../display/dc/clk_mgr/dcn60/dcn60_clk_mgr.h  |   150 +
>  .../dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.c  |   369 +
>  .../dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.h  |    35 +
>  drivers/gpu/drm/amd/display/dc/core/dc.c      |    76 +-
>  .../drm/amd/display/dc/core/dc_hw_sequencer.c |   428 +
>  .../gpu/drm/amd/display/dc/core/dc_resource.c |    47 +
>  .../gpu/drm/amd/display/dc/core/dc_state.c    |    12 +
>  .../gpu/drm/amd/display/dc/core/dc_stream.c   |    27 +-
>  drivers/gpu/drm/amd/display/dc/dc.h           |    41 +-
>  drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c  |    44 +
>  drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h  |    23 +
>  drivers/gpu/drm/amd/display/dc/dc_helper.c    |     2 +
>  drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |    53 +-
>  .../gpu/drm/amd/display/dc/dc_spl_translate.c |    32 +-
>  .../gpu/drm/amd/display/dc/dc_state_priv.h    |     1 +
>  drivers/gpu/drm/amd/display/dc/dc_stream.h    |     5 +
>  drivers/gpu/drm/amd/display/dc/dc_types.h     |    13 +-
>  drivers/gpu/drm/amd/display/dc/dccg/Makefile  |     8 +
>  .../amd/display/dc/dccg/dcn20/dcn20_dccg.h    |    10 +
>  .../amd/display/dc/dccg/dcn60/dcn60_dccg.c    |   187 +
>  .../amd/display/dc/dccg/dcn60/dcn60_dccg.h    |   182 +
>  .../drm/amd/display/dc/dce/dce_clock_source.c |    28 +
>  .../drm/amd/display/dc/dce/dce_clock_source.h |     9 +
>  drivers/gpu/drm/amd/display/dc/dio/Makefile   |     8 +
>  .../display/dc/dio/dcn10/dcn10_link_encoder.h |    16 +
>  .../dc/dio/dcn401/dcn401_dio_link_encoder.c   |    15 +
>  .../dc/dio/dcn401/dcn401_dio_link_encoder.h   |    10 +
>  .../dc/dio/dcn60/dcn60_dio_link_encoder.c     |   373 +
>  .../dc/dio/dcn60/dcn60_dio_link_encoder.h     |    43 +
>  .../dc/dio/dcn60/dcn60_dio_stream_encoder.c   |   538 +
>  .../dc/dio/dcn60/dcn60_dio_stream_encoder.h   |   181 +
>  drivers/gpu/drm/amd/display/dc/dm_helpers.h   |     8 +
>  .../amd/display/dc/dml/dcn351/dcn351_fpu.c    |     4 +-
>  .../gpu/drm/amd/display/dc/dml2_0/Makefile    |    25 +
>  .../dml2_0/dml21/dml21_translation_helper.c   |    57 +-
>  .../amd/display/dc/dml2_0/dml21/dml21_utils.c |   129 +-
>  .../dml21/inc/bounding_boxes/dcn5_soc_bb.h    |    36 +
>  .../dml21/inc/bounding_boxes/dcn6_soc_bb.h    |   229 +
>  .../bounding_boxes/utm_qos_model_dchub_v1.h   |   109 +
>  .../bounding_boxes/utm_qos_model_dchub_v2.h   |   122 +
>  .../bounding_boxes/utm_qos_model_dchub_v3.h   |    53 +
>  .../inc/bounding_boxes/utm_qos_model_types.h  |    51 +
>  .../dc/dml2_0/dml21/inc/dml_dmub_cmd.h        |   502 +
>  .../dml21/inc/dml_top_display_cfg_types.h     |    10 +
>  .../dml21/inc/dml_top_soc_parameter_types.h   |     2 +
>  .../dc/dml2_0/dml21/inc/dml_top_types.h       |    45 +
>  .../dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.c |   152 +
>  .../dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.h |     9 +
>  .../dml21/src/dml2_cga/dml2_cga_factory.c     |    38 +
>  .../dml21/src/dml2_cga/dml2_cga_factory.h     |     9 +
>  .../dml2_core_calcs_dsc_shared_types.h        |    32 +
>  .../src/dml2_core/dml2_core_dcn4_calcs.c      |     1 +
>  .../dml2_core/dml2_core_dcn5_calcs_dchub.c    |  5893 ++
>  .../dml2_core/dml2_core_dcn5_calcs_dchub.h    |   426 +
>  .../dml2_core_dcn5_calcs_display_pipe.c       |  1029 +
>  .../dml2_core_dcn5_calcs_display_pipe.h       |   151 +
>  .../dml2_core_dcn5_calcs_dsc_latency.c        |   501 +
>  .../dml2_core_dcn5_calcs_dsc_latency.h        |    23 +
>  .../dml2_core_dcn5_funcs_initialize.c         |    78 +
>  .../dml2_core_dcn5_funcs_initialize.h         |    12 +
>  .../dml2_core_dcn5_funcs_mode_programming.c   |  1791 +
>  .../dml2_core_dcn5_funcs_mode_programming.h   |    11 +
>  .../dml2_core_dcn5_funcs_mode_support.c       |  2957 +
>  .../dml2_core_dcn5_funcs_mode_support.h       |    11 +
>  .../src/dml2_core/dml2_core_dcn6_calcs.c      |    11 +
>  .../src/dml2_core/dml2_core_dcn6_calcs.h      |     8 +
>  .../dml2_core/dml2_core_dcn6_calcs_dchub.c    |  1951 +
>  .../dml2_core/dml2_core_dcn6_calcs_dchub.h    |   101 +
>  .../dml2_core_dcn6_funcs_initialize.c         |   165 +
>  .../dml2_core_dcn6_funcs_initialize.h         |    12 +
>  .../dml2_core_dcn6_funcs_mode_programming.c   |  1389 +
>  .../dml2_core_dcn6_funcs_mode_programming.h   |    11 +
>  .../dml2_core_dcn6_funcs_mode_support.c       |  4277 ++
>  .../dml2_core_dcn6_funcs_mode_support.h       |    11 +
>  .../dml21/src/dml2_core/dml2_core_factory.c   |    25 +
>  .../src/dml2_core/dml2_core_shared_types.h    |   160 +
>  .../dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c      |     1 -
>  .../dml21/src/dml2_dpmm/dml2_dpmm_dcn5.c      |   449 +
>  .../dml21/src/dml2_dpmm/dml2_dpmm_dcn5.h      |    19 +
>  .../dml21/src/dml2_dpmm/dml2_dpmm_factory.c   |    12 +
>  .../dml21/src/dml2_mcg/dml2_mcg_factory.c     |     5 +
>  .../dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c  |    57 +
>  .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.c |   522 +
>  .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.h |    21 +
>  .../dml2_pmo/dml2_pmo_dcn5_stage_optimizers.c |  2228 +
>  .../dml2_pmo/dml2_pmo_dcn5_stage_optimizers.h |    97 +
>  .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.c |   506 +
>  .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.h |    22 +
>  .../dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c |  1789 +
>  .../dml2_pmo/dml2_pmo_dcn6_stage_optimizers.h |    17 +
>  .../dml21/src/dml2_pmo/dml2_pmo_factory.c     |    34 +
>  .../alternate_pstate_shared_lib.c             |  1078 +
>  .../alternate_pstate_shared_lib.h             |   109 +
>  .../dml21/src/dml2_top/dml2_top_interfaces.c  |     7 +
>  .../dml2_0/dml21/src/dml2_top/dml2_top_utm.c  |   394 +
>  .../dml2_0/dml21/src/dml2_top/dml2_top_utm.h  |     9 +
>  .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.c    |   144 +
>  .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.h    |    11 +
>  .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c    |   405 +
>  .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.h    |    12 +
>  .../dml2_utm_soc_bb/dml2_utm_soc_bb_factory.c |    29 +
>  .../dml2_utm_soc_bb/dml2_utm_soc_bb_factory.h |    11 +
>  .../src/inc/dml2_internal_shared_types.h      |   485 +
>  .../drm/amd/display/dc/dml2_0/dml2_wrapper.h  |     8 +
>  drivers/gpu/drm/amd/display/dc/dpp/Makefile   |    17 +
>  .../amd/display/dc/dpp/dcn401/dcn401_dpp.h    |    41 +
>  .../display/dc/dpp/dcn401/dcn401_dpp_dscl.c   |    26 +-
>  .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c  |     7 +-
>  .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h  |     6 +
>  .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c  |   391 +
>  .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h  |    86 +
>  .../drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c  |   346 +
>  .../drm/amd/display/dc/dpp/dcn60/dcn60_dpp.h  |   525 +
>  .../amd/display/dc/dpp/dcn60/dcn60_dpp_dscl.c |   315 +
>  drivers/gpu/drm/amd/display/dc/dsc/Makefile   |     7 +
>  .../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c  |   447 +
>  .../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h  |   248 +
>  drivers/gpu/drm/amd/display/dc/gpio/Makefile  |    10 +
>  .../display/dc/gpio/dcn60/hw_factory_dcn60.c  |   228 +
>  .../display/dc/gpio/dcn60/hw_factory_dcn60.h  |    11 +
>  .../dc/gpio/dcn60/hw_translate_dcn60.c        |   168 +
>  .../dc/gpio/dcn60/hw_translate_dcn60.h        |    13 +
>  .../gpu/drm/amd/display/dc/gpio/ddc_regs.h    |    15 +
>  drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c  |   302 +
>  drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h  |    28 +
>  .../gpu/drm/amd/display/dc/gpio/hw_factory.c  |     4 +
>  .../drm/amd/display/dc/gpio/hw_translate.c    |     4 +
>  .../gpu/drm/amd/display/dc/hdcp/hdcp_msg.c    |     9 +
>  drivers/gpu/drm/amd/display/dc/hpo/Makefile   |     8 +
>  .../hpo/dcn31/dcn31_hpo_dp_stream_encoder.h   |    47 -
>  .../dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.c |   114 +
>  .../dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.h |    18 +
>  .../hpo/dcn60/dcn60_hpo_frl_stream_encoder.c  |   358 +
>  .../hpo/dcn60/dcn60_hpo_frl_stream_encoder.h  |    32 +
>  .../gpu/drm/amd/display/dc/hubbub/Makefile    |     8 +
>  .../display/dc/hubbub/dcn10/dcn10_hubbub.h    |   108 +
>  .../display/dc/hubbub/dcn60/dcn60_hubbub.c    |  1816 +
>  .../display/dc/hubbub/dcn60/dcn60_hubbub.h    |   207 +
>  drivers/gpu/drm/amd/display/dc/hubp/Makefile  |    16 +
>  .../amd/display/dc/hubp/dcn20/dcn20_hubp.h    |    29 +
>  .../amd/display/dc/hubp/dcn401/dcn401_hubp.c  |   201 +-
>  .../amd/display/dc/hubp/dcn401/dcn401_hubp.h  |    23 +-
>  .../amd/display/dc/hubp/dcn42/dcn42_hubp.c    |    78 +-
>  .../amd/display/dc/hubp/dcn42/dcn42_hubp.h    |    10 +-
>  .../amd/display/dc/hubp/dcn50/dcn50_hubp.c    |   532 +
>  .../amd/display/dc/hubp/dcn50/dcn50_hubp.h    |    48 +
>  .../amd/display/dc/hubp/dcn60/dcn60_hubp.c    |   472 +
>  .../amd/display/dc/hubp/dcn60/dcn60_hubp.h    |   272 +
>  drivers/gpu/drm/amd/display/dc/hwss/Makefile  |    16 +
>  .../drm/amd/display/dc/hwss/dce/dce_hwseq.h   |     9 +
>  .../amd/display/dc/hwss/dce110/dce110_hwseq.c |    21 +-
>  .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c   |     3 +-
>  .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c   |     3 +-
>  .../amd/display/dc/hwss/dcn30/dcn30_hwseq.c   |     3 +-
>  .../amd/display/dc/hwss/dcn31/dcn31_hwseq.c   |    21 +-
>  .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c   |     5 +-
>  .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c   |     8 +-
>  .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c |   483 +-
>  .../amd/display/dc/hwss/dcn401/dcn401_hwseq.h |     7 +-
>  .../amd/display/dc/hwss/dcn401/dcn401_init.c  |     1 -
>  .../amd/display/dc/hwss/dcn42/dcn42_hwseq.c   |   488 +-
>  .../amd/display/dc/hwss/dcn42/dcn42_hwseq.h   |     6 -
>  .../amd/display/dc/hwss/dcn42/dcn42_init.c    |     2 -
>  .../amd/display/dc/hwss/dcn50/dcn50_hwseq.c   |   759 +
>  .../amd/display/dc/hwss/dcn50/dcn50_hwseq.h   |    32 +
>  .../amd/display/dc/hwss/dcn60/dcn60_hwseq.c   |  1164 +
>  .../amd/display/dc/hwss/dcn60/dcn60_hwseq.h   |    32 +
>  .../amd/display/dc/hwss/dcn60/dcn60_init.c    |   181 +
>  .../amd/display/dc/hwss/dcn60/dcn60_init.h    |    12 +
>  .../drm/amd/display/dc/hwss/hw_sequencer.h    |    19 +-
>  .../display/dc/hwss/hw_sequencer_private.h    |     5 -
>  .../gpu/drm/amd/display/dc/inc/core_types.h   |     1 +
>  .../gpu/drm/amd/display/dc/inc/hw/clk_mgr.h   |     1 +
>  .../amd/display/dc/inc/hw/clk_mgr_internal.h  |    22 +
>  .../amd/display/dc/inc/hw/cursor_reg_cache.h  |     3 +-
>  drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h   |     7 +
>  drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h  |    35 +-
>  .../drm/amd/display/dc/inc/hw/link_encoder.h  |     6 +
>  drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h   |    81 +-
>  .../gpu/drm/amd/display/dc/inc/hw/transform.h |     1 +
>  drivers/gpu/drm/amd/display/dc/inc/resource.h |     2 +
>  drivers/gpu/drm/amd/display/dc/irq/Makefile   |     9 +
>  .../display/dc/irq/dcn60/irq_service_dcn60.c  |   417 +
>  .../display/dc/irq/dcn60/irq_service_dcn60.h  |    12 +
>  .../drm/amd/display/dc/link/link_detection.c  |    29 +
>  .../drm/amd/display/dc/link/link_factory.c    |     5 +
>  .../amd/display/dc/link/protocols/link_ddc.c  |     8 +
>  .../display/dc/link/protocols/link_hdmi_frl.c |    23 +-
>  drivers/gpu/drm/amd/display/dc/mpc/Makefile   |     8 +
>  .../amd/display/dc/mpc/dcn401/dcn401_mpc.c    |   177 +-
>  .../amd/display/dc/mpc/dcn401/dcn401_mpc.h    |    25 +-
>  .../drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c  |   405 +-
>  .../drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h  |    55 +-
>  .../drm/amd/display/dc/mpc/dcn60/dcn60_mpc.c  |   330 +
>  .../drm/amd/display/dc/mpc/dcn60/dcn60_mpc.h  |   472 +
>  drivers/gpu/drm/amd/display/dc/opp/Makefile   |     8 +
>  .../drm/amd/display/dc/opp/dcn60/dcn60_opp.c  |    25 +
>  .../drm/amd/display/dc/opp/dcn60/dcn60_opp.h  |    64 +
>  drivers/gpu/drm/amd/display/dc/optc/Makefile  |     9 +
>  .../amd/display/dc/optc/dcn10/dcn10_optc.c    |    36 +-
>  .../amd/display/dc/optc/dcn10/dcn10_optc.h    |     3 +-
>  .../amd/display/dc/optc/dcn31/dcn31_optc.h    |     4 +
>  .../amd/display/dc/optc/dcn314/dcn314_optc.h  |     1 +
>  .../amd/display/dc/optc/dcn32/dcn32_optc.h    |     2 +
>  .../amd/display/dc/optc/dcn35/dcn35_optc.c    |    26 +-
>  .../amd/display/dc/optc/dcn401/dcn401_optc.h  |     1 +
>  .../amd/display/dc/optc/dcn42/dcn42_optc.c    |     9 +-
>  .../amd/display/dc/optc/dcn42/dcn42_optc.h    |     4 +
>  .../amd/display/dc/optc/dcn60/dcn60_optc.c    |   107 +
>  .../amd/display/dc/optc/dcn60/dcn60_optc.h    |   178 +
>  .../gpu/drm/amd/display/dc/resource/Makefile  |    10 +
>  .../dc/resource/dcn10/dcn10_resource.c        |     1 +
>  .../dc/resource/dcn20/dcn20_resource.c        |     1 +
>  .../dc/resource/dcn201/dcn201_resource.c      |     1 +
>  .../dc/resource/dcn21/dcn21_resource.c        |     1 +
>  .../dc/resource/dcn30/dcn30_resource.c        |     2 +
>  .../dc/resource/dcn301/dcn301_resource.c      |     1 +
>  .../dc/resource/dcn302/dcn302_resource.c      |     2 +
>  .../dc/resource/dcn303/dcn303_resource.c      |     2 +
>  .../dc/resource/dcn31/dcn31_resource.c        |     1 +
>  .../dc/resource/dcn314/dcn314_resource.c      |     2 +
>  .../dc/resource/dcn315/dcn315_resource.c      |     6 +-
>  .../dc/resource/dcn316/dcn316_resource.c      |     5 +-
>  .../dc/resource/dcn32/dcn32_resource.c        |     2 +
>  .../dc/resource/dcn321/dcn321_resource.c      |     2 +
>  .../dc/resource/dcn35/dcn35_resource.c        |     2 +
>  .../dc/resource/dcn351/dcn351_resource.c      |     2 +
>  .../dc/resource/dcn36/dcn36_resource.c        |     2 +
>  .../dc/resource/dcn401/dcn401_resource.c      |    34 +-
>  .../dc/resource/dcn401/dcn401_resource.h      |     4 +
>  .../dc/resource/dcn42/dcn42_resource.c        |     3 +
>  .../dc/resource/dcn42b/dcn42b_resource.c      |    20 +-
>  .../dc/resource/dcn60/dcn60_resource.c        |  2377 +
>  .../dc/resource/dcn60/dcn60_resource.h        |   676 +
>  .../display/dc/soc_and_ip_translator/Makefile |     3 +
>  .../dcn60/dcn60_soc_and_ip_translator.c       |   117 +
>  .../dcn60/dcn60_soc_and_ip_translator.h       |    16 +
>  .../soc_and_ip_translator.c                   |     4 +
>  drivers/gpu/drm/amd/display/dmub/dmub_srv.h   |     5 +
>  .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   |   229 +-
>  drivers/gpu/drm/amd/display/dmub/src/Makefile |     1 +
>  .../gpu/drm/amd/display/dmub/src/dmub_dcn60.c |   732 +
>  .../gpu/drm/amd/display/dmub/src/dmub_dcn60.h |   303 +
>  .../gpu/drm/amd/display/dmub/src/dmub_srv.c   |    52 +
>  .../gpu/drm/amd/display/include/dal_asic_id.h |    18 +
>  .../gpu/drm/amd/display/include/dal_types.h   |     1 +
>  .../amd/display/modules/freesync/freesync.c   |     8 +-
>  .../drm/amd/display/modules/power/power_abm.c |   215 +-
>  .../amd/display/modules/power/power_helpers.h |     9 +
>  .../drm/amd/display/modules/power/power_psr.c |     7 +
>  .../amd/display/modules/power/power_replay.c  |     7 +
>  .../include/asic_reg/dcn/dcn_6_0_0_offset.h   | 15799 +++++
>  .../include/asic_reg/dcn/dcn_6_0_0_sh_mask.h  | 58556 ++++++++++++++++
>  .../include/asic_reg/dpcs/dpcs_6_0_0_offset.h |    47 +
>  .../asic_reg/dpcs/dpcs_6_0_0_sh_mask.h        |    55 +
>  .../asic_reg/mmhub/mmhub_5_0_1_offset.h       |    17 +
>  .../asic_reg/mmhub/mmhub_5_0_1_sh_mask.h      |    17 +
>  286 files changed, 129427 insertions(+), 1800 deletions(-)  create mode
> 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h create mode
> 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c create
> mode 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.c create
> mode 100644
> drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.h create
> mode 100644 drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.c create
> mode 100644 drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.h create
> mode 100644
> drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.c create
> mode 100644
> drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.h create
> mode 100644
> drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_stream_encoder.c create
> mode 100644
> drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_stream_encoder.h create
> mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn5_soc_bb.
> h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn6_soc_bb.
> h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos_mode
> l_dchub_v1.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos_mode
> l_dchub_v2.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos_mode
> l_dchub_v3.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos_mode
> l_types.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_dmub_cmd.h create mode
> 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_factory.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_factory.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_calcs_d
> sc_shared_types.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_ca
> lcs_dchub.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_ca
> lcs_dchub.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_ca
> lcs_display_pipe.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_ca
> lcs_display_pipe.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_ca
> lcs_dsc_latency.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_ca
> lcs_dsc_latency.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_fu
> ncs_initialize.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_fu
> ncs_initialize.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_fu
> ncs_mode_programming.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_fu
> ncs_mode_programming.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_fu
> ncs_mode_support.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn5_fu
> ncs_mode_support.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_ca
> lcs.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_ca
> lcs.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_ca
> lcs_dchub.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_ca
> lcs_dchub.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_fu
> ncs_initialize.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_fu
> ncs_initialize.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_fu
> ncs_mode_programming.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_fu
> ncs_mode_programming.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_fu
> ncs_mode_support.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn6_fu
> ncs_mode_support.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn5.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn5.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5_stag
> e_optimizers.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5_stag
> e_optimizers.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stag
> e_optimizers.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6_stag
> e_optimizers.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/a
> lternate_pstate_shared_lib.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_libraries/a
> lternate_pstate_shared_lib.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_utm.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_utm.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_so
> c_bb_dcn5.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_so
> c_bb_dcn5.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_so
> c_bb_dcn6.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_so
> c_bb_dcn6.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_so
> c_bb_factory.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_utm_so
> c_bb_factory.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp_dscl.c create mode
> 100644 drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c create mode
> 100644 drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h create mode
> 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_factory_dcn60.c create
> mode 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_factory_dcn60.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_translate_dcn60.c create mode
> 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_translate_dcn60.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_stream_encoder.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_stream_encoder.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hubbub/dcn60/dcn60_hubbub.c create mode
> 100644 drivers/gpu/drm/amd/display/dc/hubbub/dcn60/dcn60_hubbub.h create
> mode 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn50/dcn50_hubp.c create
> mode 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn50/dcn50_hubp.h create
> mode 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.c create
> mode 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.h create
> mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c create
> mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.h create
> mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c create
> mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.h create
> mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c create
> mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.h create
> mode 100644 drivers/gpu/drm/amd/display/dc/irq/dcn60/irq_service_dcn60.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/irq/dcn60/irq_service_dcn60.h create mode
> 100644 drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.c create mode
> 100644 drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.h create mode
> 100644 drivers/gpu/drm/amd/display/dc/opp/dcn60/dcn60_opp.c create mode
> 100644 drivers/gpu/drm/amd/display/dc/opp/dcn60/dcn60_opp.h create mode
> 100644 drivers/gpu/drm/amd/display/dc/optc/dcn60/dcn60_optc.c create mode
> 100644 drivers/gpu/drm/amd/display/dc/optc/dcn60/dcn60_optc.h create mode
> 100644 drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.h create mode
> 100644
> drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn60/dcn60_soc_and_ip
> _translator.c create mode 100644
> drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn60/dcn60_soc_and_ip
> _translator.h create mode 100644
> drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.c create mode 100644
> drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.h create mode 100644
> drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_6_0_0_offset.h create mode
> 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_6_0_0_sh_mask.h create
> mode 100644 drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_6_0_0_offset.h
> create mode 100644
> drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_6_0_0_sh_mask.h create mode
> 100644 drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_5_0_1_offset.h
> create mode 100644
> drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_5_0_1_sh_mask.h
> 
> --
> 2.34.1





^ permalink raw reply	[flat|nested] 43+ messages in thread

* RE: [PATCH 00/41] DC Patches July 31, 2026
  2026-08-04 21:15   ` Timur Kristóf
@ 2026-08-05 20:03     ` Wheeler, Daniel
  0 siblings, 0 replies; 43+ messages in thread
From: Wheeler, Daniel @ 2026-08-05 20:03 UTC (permalink / raw)
  To: Timur Kristóf, Li, Roman, amd-gfx@lists.freedesktop.org
  Cc: Wentland, Harry, Li, Sun peng (Leo), Pillai, Aurabindo, Li, Roman,
	Lin, Wayne, Chung, ChiaHsuan (Tom), Zuo, Jerry, Wu, Ray,
	LIPSKI, IVAN, Hung, Alex, Lin, Ping Lei, Chen, Chen-Yu, Li, Roman,
	Deucher, Alexander

Public

Hey Timur,

The most helpful thing the community can do is to file tickets at https://gitlab.freedesktop.org/drm/amd. We've created a few new tools that will help us get through the tickets posted here from the community.

As for Vega and older GPUs, they were part of our automated tests but were removed. We'll readd them to the test farm, initially Vega for boot testing, and we can see how that goes.

Thank you,

Dan Wheeler
Sr. Technologist | AMD
SW Display
------------------------------------------------------------------------------------------------------------------
1 Commerce Valley Dr E, Thornhill, ON L3T 7X6
amd.com


-----Original Message-----
From: Timur Kristóf <timur.kristof@gmail.com>
Sent: Tuesday, August 4, 2026 5:16 PM
To: Li, Roman <Roman.Li@amd.com>; amd-gfx@lists.freedesktop.org
Cc: Wentland, Harry <Harry.Wentland@amd.com>; Li, Sun peng (Leo) <Sunpeng.Li@amd.com>; Pillai, Aurabindo <Aurabindo.Pillai@amd.com>; Li, Roman <Roman.Li@amd.com>; Lin, Wayne <Wayne.Lin@amd.com>; Chung, ChiaHsuan (Tom) <ChiaHsuan.Chung@amd.com>; Zuo, Jerry <Jerry.Zuo@amd.com>; Wu, Ray <Ray.Wu@amd.com>; LIPSKI, IVAN <IVAN.LIPSKI@amd.com>; Hung, Alex <Alex.Hung@amd.com>; Lin, Ping Lei <PingLei.Lin@amd.com>; Chen, Chen-Yu <Chen-Yu.Chen@amd.com>; Li, Roman <Roman.Li@amd.com>; Wheeler, Daniel <Daniel.Wheeler@amd.com>; Deucher, Alexander <Alexander.Deucher@amd.com>
Subject: Re: [PATCH 00/41] DC Patches July 31, 2026

On Tuesday, August 4, 2026 3:24:14 PM Central European Summer Time Wheeler, Daniel wrote:
> Public
>
> Hi all,
>
> This week this patchset was tested on 4 systems, two dGPU and two APU
> based, and tested across multiple display and connection types.

Hi Daniel,

Is there any way the community could contribute to help prevent regressions?

I respect that AMD wants to minimize time and resources spent on development for legacy GPUs, that is understandable and reasonable. However, could we please find a way to try to minimize regressions? For example, at the very least, would it be feasible to make sure that all supported GPUs can boot to a functional graphical desktop without crashing or showing a black screen?

Current amd-staging-drm-next is broken on all Vega and older GPUs since the 20th July DC patch series. Basically the display driver just crashes on boot.
I already sent fixes for two regressions, and we're still looking for one more.

Thanks & best regards,
Timur

>
> APU
>         * Single Display eDP -> 1080p 60hz, 1920x1200 165hz, 3840x2400 60hz
>         * Single Display DP (SST DSC) -> 4k144hz, 4k240hz
>         * Multi display -> eDP + DP/HDMI/USB-C -> 1080p 60hz eDP + 4k
> 144hz, 4k 240hz (Includes USB-C to DP/HDMI adapters) * Thunderbolt ->
> LG Ultrafine 5k
>         * MST DSC -> Cable Matters 101075 (DP to 3x DP) with 3x 4k60hz
> displays, HP Hook G2 with 2x 4k60hz displays * USB 4 -> HP Hook G4,
> Lenovo Thunderbolt Dock, both with 2x 4k60hz DP and 1x 4k60hz HDMI
> displays * SST PCON -> Club3D CAC-1085 + 1x 4k 144hz, FRL3, at a max
> resolution supported by the dongle of 4k 120hz YUV420 12bpc. * MST
> PCON -> 1x 4k 144hz, FRL3, at a max resolution supported by the adapter of 4k 120hz RGB 8bpc.
>
> DGPU
>         * Single Display DP (SST DSC) -> 4k144hz, 4k240hz
>         * Multiple Display DP -> 4k240hz + 4k144hz
>         * MST (Startech MST14DP123DP [DP to 3x DP] and 2x 4k 60hz displays)
>         * MST DSC (with Cable Matters 101075 [DP to 3x DP] with 3x
> 4k60hz
> displays)
>
> The testing is a mix of automated and manual tests. Manual testing
> includes (but is not limited to) * Changing display configurations and settings
>         * Video/Audio playback
>         * Benchmark testing
>         * Suspend/Resume testing
>         * Feature testing (Freesync, HDCP, etc.)
>
> Automated testing includes (but is not limited to)
>         * Script testing (scripts to automate some of the manual checks)
>         * IGT testing
>
> The testing is mainly tested on the following displays, but
> occasionally there are tests with other displays * Samsung G8 Neo 4k240hz
>         * Samsung QN55QN95B 4k 120hz
>         * Acer XV322QKKV 4k144hz
>         * HP U27 4k Wireless 4k60hz
>         * LG 27UD58B 4k60hz
>         * LG 32UN650WA 4k60hz
>         * LG Ultrafine 5k 5k60hz
>         * AU Optronics B140HAN01.1 1080p 60hz eDP
>         * AU Optronics B160UAN01.J 1920x1200 165hz eDP
>         * Samsung ATNA60YV02-0 3840x2400 60Hz OLED eDP
>
>
> The patchset consists of the amd-staging-drm-next branch (Head commit
> -
> 76e667ef60446d435b869360961888cca1500cb6 -> drm/amd/display: use
> proper context for logging) with new patches added on top of it.
>
> Tested on Ubuntu 26.04.1, on Gnome Wayland.
>
> Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
>
> Thank you,
>
> Dan Wheeler
> Sr. Technologist | AMD
> SW Display
> ----------------------------------------------------------------------
> ------
> -------------------------------------- 1 Commerce Valley Dr E,
> Thornhill, ON L3T 7X6 amd.com
>
>
> -----Original Message-----
> From: Roman.Li@amd.com <Roman.Li@amd.com>
> Sent: Friday, July 31, 2026 5:12 PM
> To: amd-gfx@lists.freedesktop.org
> Cc: Wentland, Harry <Harry.Wentland@amd.com>; Li, Sun peng (Leo)
> <Sunpeng.Li@amd.com>; Pillai, Aurabindo <Aurabindo.Pillai@amd.com>;
> Li, Roman <Roman.Li@amd.com>; Lin, Wayne <Wayne.Lin@amd.com>; Chung,
> ChiaHsuan
> (Tom) <ChiaHsuan.Chung@amd.com>; Zuo, Jerry <Jerry.Zuo@amd.com>;
> Wheeler, Daniel <Daniel.Wheeler@amd.com>; Wu, Ray <Ray.Wu@amd.com>;
> LIPSKI, IVAN <IVAN.LIPSKI@amd.com>; Hung, Alex <Alex.Hung@amd.com>;
> Lin, Ping Lei <PingLei.Lin@amd.com>; Chen, Chen-Yu
> <Chen-Yu.Chen@amd.com>; Li, Roman <Roman.Li@amd.com> Subject: [PATCH
> 00/41] DC Patches July 31, 2026
>
> From: Roman Li <Roman.Li@amd.com>
>
> This DC patchset brings improvements in multiple areas. In summary, we
> highlight: - Add KUnit tests for crtc functions
>  - Enable DCN6
>  - Fix ABM, CRC engine, MCM, writeback issues
>  - Refactor stream validation.
>
> Cc: Dan Wheeler <daniel.wheeler@amd.com>
>
> Alex Hung (2):
>   drm/amd/display: Fix wb_info leak and NULL deref in writeback
>   drm/amd/display: Fix more KUnit connector use-after-free bugs
>
> Alvin Lee (1):
>   drm/amd/display: Update BW bounding box unconditionally for DCN6
>
> Aurabindo Pillai (5):
>   drm/amd: Add DCN6 register headers
>   drm/amd/display: Add new sources for DCN6
>   drm/amd/display: Enable DCN6 init
>   drm/amd/display: Dependent changes for DCN6
>   drm/amd/display: Enable DCN6 sources compilation
>
> Bhawanpreet Lakha (12):
>   drm/amd/display: Add KUnit tests for more crtc functions
>   drm/amd/display: Add vblank handling tests for crtc
>   drm/amd/display: Add idle worker tests for crtc
>   drm/amd/display: Add active plane count tests for crtc
>   drm/amd/display: Add KUnit test for crtc vblank event completion
>   drm/amd/display: Add KUnit tests for crtc set_vupdate_irq
>   drm/amd/display: Add KUnit tests for crtc set_static_screen_optimze
>   drm/amd/display: Add KUnit tests for crtc set_vblank
>   drm/amd/display: Cover crtc set_vblank workqueue branch
>   drm/amd/display: Cover crtc vblank IPS self-refresh restore
>   drm/amd/display: Cover crtc vblank restore replay-supported path
>   drm/amd/display: Cover crtc destroy_state stream release
>
> Charlene Liu (1):
>   drm/amd/display: Ensure dtbclk is enabled
>
> Fangzhi Zuo (1):
>   drm/amd/display: Gate HDMI FRL status polling on active FRL link
> rate
>
> Harry VanZyllDeJong (1):
>   drm/amd/display: Update VRR info packet to support 12-bit refresh
>     rates
>
> Harry Wentland (2):
>   drm/amd/display: Resize MST HDCP per-connector arrays to 32
>   drm/amd/display: Bounds-check connector->index in
> dm_dp_mst_get_modes
>
> Iswara Nagulendran (1):
>   drm/amd/display: Fix ABM over VABC
>
> Ivan Lipski (3):
>   drm/amd/display: Refactor stream validation
>   drm/amd/display: Unify force_yuv debugfs into force_yuv_pixel_format
>   drm/amd/display: Align connector KUnit tests with stream validation
>     refactor
>
> Karthi Kandasamy (1):
>   drm/amd/display: Fix seamless mode switch not triggering for HDR to
>     SDR transition
>
> Matthew Stewart (1):
>   drm/amd/display: Add missing DCN42B register defines
>
> Rafal Ostrowski (1):
>   drm/amd/display: Migrate color manager HW and fix MCM blend LUT
> issues
>
> Relja Vojvodic (2):
>   drm/amd/display: switch max FFE level cap based on FRL link rate
>   drm/amd/display: Add FFE level defaults
>
> Roman Li (1):
>   drm/amd/display: Remove duplicate in tests/Makefile
>
> Sung-huai Wang (1):
>   drm/amd/display: Increase fclk change latency on dcn351
>
> Taimur Hassan (2):
>   drm/amd/display: Add missing DMUB CACP and PR definitions
>   drm/amd/display: Promote DC to 3.2.392
>
> Wayne Lin (3):
>   drm/amd/display: Add missing OTG_CRC1_SELECT mask for DCN3.2
>   drm/amd/display: Fix CRC engine 1 enable/disable on DCN3.1.2+
>   drm/amd/display: Configure all CRC engines in pipe CRC source path
>
>  drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c |     1 +
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |    31 +-
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h |     2 -
>  .../amd/display/amdgpu_dm/amdgpu_dm_audio.h   |     2 +-
>  .../display/amdgpu_dm/amdgpu_dm_connector.c   |   289 +-
>  .../display/amdgpu_dm/amdgpu_dm_connector.h   |     8 +-
>  .../drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c |    13 +-
>  .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c    |    25 +-
>  .../amd/display/amdgpu_dm/amdgpu_dm_crtc.h    |     9 +
>  .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c |    57 +-
>  .../amd/display/amdgpu_dm/amdgpu_dm_dmub.c    |    10 +
>  .../amd/display/amdgpu_dm/amdgpu_dm_dmub.h    |     1 +
>  .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.c    |    10 +-
>  .../amd/display/amdgpu_dm/amdgpu_dm_hdcp.h    |    10 +-
>  .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c |     6 +
>  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |     3 +-
>  .../amd/display/amdgpu_dm/amdgpu_dm_plane.c   |     9 +-
>  .../drm/amd/display/amdgpu_dm/tests/Makefile  |     1 -
>  .../tests/amdgpu_dm_connector_test.c          |   163 +-
>  .../amdgpu_dm/tests/amdgpu_dm_crtc_test.c     |  1436 +
>  .../amdgpu_dm/tests/amdgpu_dm_kunit_helpers.c |    29 +
>  .../tests/amdgpu_dm_kunit_test_helpers.h      |     3 +
>  .../display/dc/bios/command_table_helper2.c   |     1 +
>  .../gpu/drm/amd/display/dc/clk_mgr/Makefile   |     9 +
>  .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c  |    15 +
>  .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c  |    28 +-
>  .../display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h  |     1 +
>  .../drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h |   389 +
>  .../display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c  |  1673 +
>  .../display/dc/clk_mgr/dcn60/dcn60_clk_mgr.h  |   150 +
>  .../dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.c  |   369 +
>  .../dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.h  |    35 +
>  drivers/gpu/drm/amd/display/dc/core/dc.c      |    76 +-
>  .../drm/amd/display/dc/core/dc_hw_sequencer.c |   428 +
>  .../gpu/drm/amd/display/dc/core/dc_resource.c |    47 +
>  .../gpu/drm/amd/display/dc/core/dc_state.c    |    12 +
>  .../gpu/drm/amd/display/dc/core/dc_stream.c   |    27 +-
>  drivers/gpu/drm/amd/display/dc/dc.h           |    41 +-
>  drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c  |    44 +
>  drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h  |    23 +
>  drivers/gpu/drm/amd/display/dc/dc_helper.c    |     2 +
>  drivers/gpu/drm/amd/display/dc/dc_hw_types.h  |    53 +-
>  .../gpu/drm/amd/display/dc/dc_spl_translate.c |    32 +-
>  .../gpu/drm/amd/display/dc/dc_state_priv.h    |     1 +
>  drivers/gpu/drm/amd/display/dc/dc_stream.h    |     5 +
>  drivers/gpu/drm/amd/display/dc/dc_types.h     |    13 +-
>  drivers/gpu/drm/amd/display/dc/dccg/Makefile  |     8 +
>  .../amd/display/dc/dccg/dcn20/dcn20_dccg.h    |    10 +
>  .../amd/display/dc/dccg/dcn60/dcn60_dccg.c    |   187 +
>  .../amd/display/dc/dccg/dcn60/dcn60_dccg.h    |   182 +
>  .../drm/amd/display/dc/dce/dce_clock_source.c |    28 +
>  .../drm/amd/display/dc/dce/dce_clock_source.h |     9 +
>  drivers/gpu/drm/amd/display/dc/dio/Makefile   |     8 +
>  .../display/dc/dio/dcn10/dcn10_link_encoder.h |    16 +
>  .../dc/dio/dcn401/dcn401_dio_link_encoder.c   |    15 +
>  .../dc/dio/dcn401/dcn401_dio_link_encoder.h   |    10 +
>  .../dc/dio/dcn60/dcn60_dio_link_encoder.c     |   373 +
>  .../dc/dio/dcn60/dcn60_dio_link_encoder.h     |    43 +
>  .../dc/dio/dcn60/dcn60_dio_stream_encoder.c   |   538 +
>  .../dc/dio/dcn60/dcn60_dio_stream_encoder.h   |   181 +
>  drivers/gpu/drm/amd/display/dc/dm_helpers.h   |     8 +
>  .../amd/display/dc/dml/dcn351/dcn351_fpu.c    |     4 +-
>  .../gpu/drm/amd/display/dc/dml2_0/Makefile    |    25 +
>  .../dml2_0/dml21/dml21_translation_helper.c   |    57 +-
>  .../amd/display/dc/dml2_0/dml21/dml21_utils.c |   129 +-
>  .../dml21/inc/bounding_boxes/dcn5_soc_bb.h    |    36 +
>  .../dml21/inc/bounding_boxes/dcn6_soc_bb.h    |   229 +
>  .../bounding_boxes/utm_qos_model_dchub_v1.h   |   109 +
>  .../bounding_boxes/utm_qos_model_dchub_v2.h   |   122 +
>  .../bounding_boxes/utm_qos_model_dchub_v3.h   |    53 +
>  .../inc/bounding_boxes/utm_qos_model_types.h  |    51 +
>  .../dc/dml2_0/dml21/inc/dml_dmub_cmd.h        |   502 +
>  .../dml21/inc/dml_top_display_cfg_types.h     |    10 +
>  .../dml21/inc/dml_top_soc_parameter_types.h   |     2 +
>  .../dc/dml2_0/dml21/inc/dml_top_types.h       |    45 +
>  .../dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.c |   152 +
>  .../dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6.h |     9 +
>  .../dml21/src/dml2_cga/dml2_cga_factory.c     |    38 +
>  .../dml21/src/dml2_cga/dml2_cga_factory.h     |     9 +
>  .../dml2_core_calcs_dsc_shared_types.h        |    32 +
>  .../src/dml2_core/dml2_core_dcn4_calcs.c      |     1 +
>  .../dml2_core/dml2_core_dcn5_calcs_dchub.c    |  5893 ++
>  .../dml2_core/dml2_core_dcn5_calcs_dchub.h    |   426 +
>  .../dml2_core_dcn5_calcs_display_pipe.c       |  1029 +
>  .../dml2_core_dcn5_calcs_display_pipe.h       |   151 +
>  .../dml2_core_dcn5_calcs_dsc_latency.c        |   501 +
>  .../dml2_core_dcn5_calcs_dsc_latency.h        |    23 +
>  .../dml2_core_dcn5_funcs_initialize.c         |    78 +
>  .../dml2_core_dcn5_funcs_initialize.h         |    12 +
>  .../dml2_core_dcn5_funcs_mode_programming.c   |  1791 +
>  .../dml2_core_dcn5_funcs_mode_programming.h   |    11 +
>  .../dml2_core_dcn5_funcs_mode_support.c       |  2957 +
>  .../dml2_core_dcn5_funcs_mode_support.h       |    11 +
>  .../src/dml2_core/dml2_core_dcn6_calcs.c      |    11 +
>  .../src/dml2_core/dml2_core_dcn6_calcs.h      |     8 +
>  .../dml2_core/dml2_core_dcn6_calcs_dchub.c    |  1951 +
>  .../dml2_core/dml2_core_dcn6_calcs_dchub.h    |   101 +
>  .../dml2_core_dcn6_funcs_initialize.c         |   165 +
>  .../dml2_core_dcn6_funcs_initialize.h         |    12 +
>  .../dml2_core_dcn6_funcs_mode_programming.c   |  1389 +
>  .../dml2_core_dcn6_funcs_mode_programming.h   |    11 +
>  .../dml2_core_dcn6_funcs_mode_support.c       |  4277 ++
>  .../dml2_core_dcn6_funcs_mode_support.h       |    11 +
>  .../dml21/src/dml2_core/dml2_core_factory.c   |    25 +
>  .../src/dml2_core/dml2_core_shared_types.h    |   160 +
>  .../dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c      |     1 -
>  .../dml21/src/dml2_dpmm/dml2_dpmm_dcn5.c      |   449 +
>  .../dml21/src/dml2_dpmm/dml2_dpmm_dcn5.h      |    19 +
>  .../dml21/src/dml2_dpmm/dml2_dpmm_factory.c   |    12 +
>  .../dml21/src/dml2_mcg/dml2_mcg_factory.c     |     5 +
>  .../dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c  |    57 +
>  .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.c |   522 +
>  .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5.h |    21 +
>  .../dml2_pmo/dml2_pmo_dcn5_stage_optimizers.c |  2228 +
>  .../dml2_pmo/dml2_pmo_dcn5_stage_optimizers.h |    97 +
>  .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.c |   506 +
>  .../dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6.h |    22 +
>  .../dml2_pmo/dml2_pmo_dcn6_stage_optimizers.c |  1789 +
>  .../dml2_pmo/dml2_pmo_dcn6_stage_optimizers.h |    17 +
>  .../dml21/src/dml2_pmo/dml2_pmo_factory.c     |    34 +
>  .../alternate_pstate_shared_lib.c             |  1078 +
>  .../alternate_pstate_shared_lib.h             |   109 +
>  .../dml21/src/dml2_top/dml2_top_interfaces.c  |     7 +
>  .../dml2_0/dml21/src/dml2_top/dml2_top_utm.c  |   394 +
>  .../dml2_0/dml21/src/dml2_top/dml2_top_utm.h  |     9 +
>  .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.c    |   144 +
>  .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn5.h    |    11 +
>  .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.c    |   405 +
>  .../dml2_utm_soc_bb/dml2_utm_soc_bb_dcn6.h    |    12 +
>  .../dml2_utm_soc_bb/dml2_utm_soc_bb_factory.c |    29 +
>  .../dml2_utm_soc_bb/dml2_utm_soc_bb_factory.h |    11 +
>  .../src/inc/dml2_internal_shared_types.h      |   485 +
>  .../drm/amd/display/dc/dml2_0/dml2_wrapper.h  |     8 +
>  drivers/gpu/drm/amd/display/dc/dpp/Makefile   |    17 +
>  .../amd/display/dc/dpp/dcn401/dcn401_dpp.h    |    41 +
>  .../display/dc/dpp/dcn401/dcn401_dpp_dscl.c   |    26 +-
>  .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c  |     7 +-
>  .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h  |     6 +
>  .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c  |   391 +
>  .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h  |    86 +
>  .../drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c  |   346 +
>  .../drm/amd/display/dc/dpp/dcn60/dcn60_dpp.h  |   525 +
>  .../amd/display/dc/dpp/dcn60/dcn60_dpp_dscl.c |   315 +
>  drivers/gpu/drm/amd/display/dc/dsc/Makefile   |     7 +
>  .../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c  |   447 +
>  .../drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h  |   248 +
>  drivers/gpu/drm/amd/display/dc/gpio/Makefile  |    10 +
>  .../display/dc/gpio/dcn60/hw_factory_dcn60.c  |   228 +
>  .../display/dc/gpio/dcn60/hw_factory_dcn60.h  |    11 +
>  .../dc/gpio/dcn60/hw_translate_dcn60.c        |   168 +
>  .../dc/gpio/dcn60/hw_translate_dcn60.h        |    13 +
>  .../gpu/drm/amd/display/dc/gpio/ddc_regs.h    |    15 +
>  drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.c  |   302 +
>  drivers/gpu/drm/amd/display/dc/gpio/hw_ddc.h  |    28 +
>  .../gpu/drm/amd/display/dc/gpio/hw_factory.c  |     4 +
>  .../drm/amd/display/dc/gpio/hw_translate.c    |     4 +
>  .../gpu/drm/amd/display/dc/hdcp/hdcp_msg.c    |     9 +
>  drivers/gpu/drm/amd/display/dc/hpo/Makefile   |     8 +
>  .../hpo/dcn31/dcn31_hpo_dp_stream_encoder.h   |    47 -
>  .../dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.c |   114 +
>  .../dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.h |    18 +
>  .../hpo/dcn60/dcn60_hpo_frl_stream_encoder.c  |   358 +
>  .../hpo/dcn60/dcn60_hpo_frl_stream_encoder.h  |    32 +
>  .../gpu/drm/amd/display/dc/hubbub/Makefile    |     8 +
>  .../display/dc/hubbub/dcn10/dcn10_hubbub.h    |   108 +
>  .../display/dc/hubbub/dcn60/dcn60_hubbub.c    |  1816 +
>  .../display/dc/hubbub/dcn60/dcn60_hubbub.h    |   207 +
>  drivers/gpu/drm/amd/display/dc/hubp/Makefile  |    16 +
>  .../amd/display/dc/hubp/dcn20/dcn20_hubp.h    |    29 +
>  .../amd/display/dc/hubp/dcn401/dcn401_hubp.c  |   201 +-
>  .../amd/display/dc/hubp/dcn401/dcn401_hubp.h  |    23 +-
>  .../amd/display/dc/hubp/dcn42/dcn42_hubp.c    |    78 +-
>  .../amd/display/dc/hubp/dcn42/dcn42_hubp.h    |    10 +-
>  .../amd/display/dc/hubp/dcn50/dcn50_hubp.c    |   532 +
>  .../amd/display/dc/hubp/dcn50/dcn50_hubp.h    |    48 +
>  .../amd/display/dc/hubp/dcn60/dcn60_hubp.c    |   472 +
>  .../amd/display/dc/hubp/dcn60/dcn60_hubp.h    |   272 +
>  drivers/gpu/drm/amd/display/dc/hwss/Makefile  |    16 +
>  .../drm/amd/display/dc/hwss/dce/dce_hwseq.h   |     9 +
>  .../amd/display/dc/hwss/dce110/dce110_hwseq.c |    21 +-
>  .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c   |     3 +-
>  .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c   |     3 +-
>  .../amd/display/dc/hwss/dcn30/dcn30_hwseq.c   |     3 +-
>  .../amd/display/dc/hwss/dcn31/dcn31_hwseq.c   |    21 +-
>  .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c   |     5 +-
>  .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c   |     8 +-
>  .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c |   483 +-
>  .../amd/display/dc/hwss/dcn401/dcn401_hwseq.h |     7 +-
>  .../amd/display/dc/hwss/dcn401/dcn401_init.c  |     1 -
>  .../amd/display/dc/hwss/dcn42/dcn42_hwseq.c   |   488 +-
>  .../amd/display/dc/hwss/dcn42/dcn42_hwseq.h   |     6 -
>  .../amd/display/dc/hwss/dcn42/dcn42_init.c    |     2 -
>  .../amd/display/dc/hwss/dcn50/dcn50_hwseq.c   |   759 +
>  .../amd/display/dc/hwss/dcn50/dcn50_hwseq.h   |    32 +
>  .../amd/display/dc/hwss/dcn60/dcn60_hwseq.c   |  1164 +
>  .../amd/display/dc/hwss/dcn60/dcn60_hwseq.h   |    32 +
>  .../amd/display/dc/hwss/dcn60/dcn60_init.c    |   181 +
>  .../amd/display/dc/hwss/dcn60/dcn60_init.h    |    12 +
>  .../drm/amd/display/dc/hwss/hw_sequencer.h    |    19 +-
>  .../display/dc/hwss/hw_sequencer_private.h    |     5 -
>  .../gpu/drm/amd/display/dc/inc/core_types.h   |     1 +
>  .../gpu/drm/amd/display/dc/inc/hw/clk_mgr.h   |     1 +
>  .../amd/display/dc/inc/hw/clk_mgr_internal.h  |    22 +
>  .../amd/display/dc/inc/hw/cursor_reg_cache.h  |     3 +-
>  drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h   |     7 +
>  drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h  |    35 +-
>  .../drm/amd/display/dc/inc/hw/link_encoder.h  |     6 +
>  drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h   |    81 +-
>  .../gpu/drm/amd/display/dc/inc/hw/transform.h |     1 +
>  drivers/gpu/drm/amd/display/dc/inc/resource.h |     2 +
>  drivers/gpu/drm/amd/display/dc/irq/Makefile   |     9 +
>  .../display/dc/irq/dcn60/irq_service_dcn60.c  |   417 +
>  .../display/dc/irq/dcn60/irq_service_dcn60.h  |    12 +
>  .../drm/amd/display/dc/link/link_detection.c  |    29 +
>  .../drm/amd/display/dc/link/link_factory.c    |     5 +
>  .../amd/display/dc/link/protocols/link_ddc.c  |     8 +
>  .../display/dc/link/protocols/link_hdmi_frl.c |    23 +-
>  drivers/gpu/drm/amd/display/dc/mpc/Makefile   |     8 +
>  .../amd/display/dc/mpc/dcn401/dcn401_mpc.c    |   177 +-
>  .../amd/display/dc/mpc/dcn401/dcn401_mpc.h    |    25 +-
>  .../drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c  |   405 +-
>  .../drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h  |    55 +-
>  .../drm/amd/display/dc/mpc/dcn60/dcn60_mpc.c  |   330 +
>  .../drm/amd/display/dc/mpc/dcn60/dcn60_mpc.h  |   472 +
>  drivers/gpu/drm/amd/display/dc/opp/Makefile   |     8 +
>  .../drm/amd/display/dc/opp/dcn60/dcn60_opp.c  |    25 +
>  .../drm/amd/display/dc/opp/dcn60/dcn60_opp.h  |    64 +
>  drivers/gpu/drm/amd/display/dc/optc/Makefile  |     9 +
>  .../amd/display/dc/optc/dcn10/dcn10_optc.c    |    36 +-
>  .../amd/display/dc/optc/dcn10/dcn10_optc.h    |     3 +-
>  .../amd/display/dc/optc/dcn31/dcn31_optc.h    |     4 +
>  .../amd/display/dc/optc/dcn314/dcn314_optc.h  |     1 +
>  .../amd/display/dc/optc/dcn32/dcn32_optc.h    |     2 +
>  .../amd/display/dc/optc/dcn35/dcn35_optc.c    |    26 +-
>  .../amd/display/dc/optc/dcn401/dcn401_optc.h  |     1 +
>  .../amd/display/dc/optc/dcn42/dcn42_optc.c    |     9 +-
>  .../amd/display/dc/optc/dcn42/dcn42_optc.h    |     4 +
>  .../amd/display/dc/optc/dcn60/dcn60_optc.c    |   107 +
>  .../amd/display/dc/optc/dcn60/dcn60_optc.h    |   178 +
>  .../gpu/drm/amd/display/dc/resource/Makefile  |    10 +
>  .../dc/resource/dcn10/dcn10_resource.c        |     1 +
>  .../dc/resource/dcn20/dcn20_resource.c        |     1 +
>  .../dc/resource/dcn201/dcn201_resource.c      |     1 +
>  .../dc/resource/dcn21/dcn21_resource.c        |     1 +
>  .../dc/resource/dcn30/dcn30_resource.c        |     2 +
>  .../dc/resource/dcn301/dcn301_resource.c      |     1 +
>  .../dc/resource/dcn302/dcn302_resource.c      |     2 +
>  .../dc/resource/dcn303/dcn303_resource.c      |     2 +
>  .../dc/resource/dcn31/dcn31_resource.c        |     1 +
>  .../dc/resource/dcn314/dcn314_resource.c      |     2 +
>  .../dc/resource/dcn315/dcn315_resource.c      |     6 +-
>  .../dc/resource/dcn316/dcn316_resource.c      |     5 +-
>  .../dc/resource/dcn32/dcn32_resource.c        |     2 +
>  .../dc/resource/dcn321/dcn321_resource.c      |     2 +
>  .../dc/resource/dcn35/dcn35_resource.c        |     2 +
>  .../dc/resource/dcn351/dcn351_resource.c      |     2 +
>  .../dc/resource/dcn36/dcn36_resource.c        |     2 +
>  .../dc/resource/dcn401/dcn401_resource.c      |    34 +-
>  .../dc/resource/dcn401/dcn401_resource.h      |     4 +
>  .../dc/resource/dcn42/dcn42_resource.c        |     3 +
>  .../dc/resource/dcn42b/dcn42b_resource.c      |    20 +-
>  .../dc/resource/dcn60/dcn60_resource.c        |  2377 +
>  .../dc/resource/dcn60/dcn60_resource.h        |   676 +
>  .../display/dc/soc_and_ip_translator/Makefile |     3 +
>  .../dcn60/dcn60_soc_and_ip_translator.c       |   117 +
>  .../dcn60/dcn60_soc_and_ip_translator.h       |    16 +
>  .../soc_and_ip_translator.c                   |     4 +
>  drivers/gpu/drm/amd/display/dmub/dmub_srv.h   |     5 +
>  .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h   |   229 +-
>  drivers/gpu/drm/amd/display/dmub/src/Makefile |     1 +
>  .../gpu/drm/amd/display/dmub/src/dmub_dcn60.c |   732 +
>  .../gpu/drm/amd/display/dmub/src/dmub_dcn60.h |   303 +
>  .../gpu/drm/amd/display/dmub/src/dmub_srv.c   |    52 +
>  .../gpu/drm/amd/display/include/dal_asic_id.h |    18 +
>  .../gpu/drm/amd/display/include/dal_types.h   |     1 +
>  .../amd/display/modules/freesync/freesync.c   |     8 +-
>  .../drm/amd/display/modules/power/power_abm.c |   215 +-
>  .../amd/display/modules/power/power_helpers.h |     9 +
>  .../drm/amd/display/modules/power/power_psr.c |     7 +
>  .../amd/display/modules/power/power_replay.c  |     7 +
>  .../include/asic_reg/dcn/dcn_6_0_0_offset.h   | 15799 +++++
>  .../include/asic_reg/dcn/dcn_6_0_0_sh_mask.h  | 58556 ++++++++++++++++
>  .../include/asic_reg/dpcs/dpcs_6_0_0_offset.h |    47 +
>  .../asic_reg/dpcs/dpcs_6_0_0_sh_mask.h        |    55 +
>  .../asic_reg/mmhub/mmhub_5_0_1_offset.h       |    17 +
>  .../asic_reg/mmhub/mmhub_5_0_1_sh_mask.h      |    17 +
>  286 files changed, 129427 insertions(+), 1800 deletions(-)  create
> mode
> 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h create
> mode
> 100644 drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr_smu_msg.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.c create mode
> 100644 drivers/gpu/drm/amd/display/dc/dccg/dcn60/dcn60_dccg.h create
> mode 100644
> drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_link_encoder.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_stream_encoder.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dio/dcn60/dcn60_dio_stream_encoder.h
> create mode 100644 drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn5_soc_bb.
> h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn6_soc_bb.
> h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos
> _mode
> l_dchub_v1.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos
> _mode
> l_dchub_v2.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos
> _mode
> l_dchub_v3.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/utm_qos
> _mode
> l_types.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_dmub_cmd.h create
> mode
> 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6
> .c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_dcn6
> .h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_fact
> ory.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_cga/dml2_cga_fact
> ory.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_ca
> lcs_d
> sc_shared_types.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n5_ca
> lcs_dchub.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n5_ca
> lcs_dchub.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n5_ca
> lcs_display_pipe.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n5_ca
> lcs_display_pipe.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n5_ca
> lcs_dsc_latency.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n5_ca
> lcs_dsc_latency.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n5_fu
> ncs_initialize.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n5_fu
> ncs_initialize.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n5_fu ncs_mode_programming.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n5_fu ncs_mode_programming.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n5_fu
> ncs_mode_support.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n5_fu
> ncs_mode_support.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n6_ca
> lcs.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n6_ca
> lcs.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n6_ca
> lcs_dchub.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n6_ca
> lcs_dchub.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n6_fu
> ncs_initialize.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n6_fu
> ncs_initialize.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n6_fu ncs_mode_programming.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n6_fu ncs_mode_programming.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n6_fu
> ncs_mode_support.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dc
> n6_fu
> ncs_mode_support.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dc
> n5.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dc
> n5.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5
> .c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5
> .h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5
> _stag
> e_optimizers.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn5
> _stag
> e_optimizers.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6
> .c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6
> .h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6
> _stag
> e_optimizers.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn6
> _stag
> e_optimizers.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_librar
> ies/a lternate_pstate_shared_lib.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_standalone_librar
> ies/a lternate_pstate_shared_lib.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_utm.
> c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_utm.
> h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_u
> tm_so
> c_bb_dcn5.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_u
> tm_so
> c_bb_dcn5.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_u
> tm_so
> c_bb_dcn6.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_u
> tm_so
> c_bb_dcn6.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_u
> tm_so
> c_bb_factory.c create mode 100644
> drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_utm_soc_bb/dml2_u
> tm_so
> c_bb_factory.h create mode 100644
> drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c create mode
> 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h create
> mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.h create mode
> 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp_dscl.c
> create mode
> 100644 drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.c create
> mode
> 100644 drivers/gpu/drm/amd/display/dc/dsc/dcn60/dcn60_dsc.h create
> mode
> 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_factory_dcn60.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_factory_dcn60.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_translate_dcn60.c create
> mode
> 100644 drivers/gpu/drm/amd/display/dc/gpio/dcn60/hw_translate_dcn60.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_link_encoder.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_stream_encoder.
> c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hpo/dcn60/dcn60_hpo_frl_stream_encoder.
> h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hubbub/dcn60/dcn60_hubbub.c create mode
> 100644 drivers/gpu/drm/amd/display/dc/hubbub/dcn60/dcn60_hubbub.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hubp/dcn50/dcn50_hubp.c create mode
> 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn50/dcn50_hubp.h create
> mode 100644 drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hubp/dcn60/dcn60_hubp.h create mode
> 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c create
> mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.h
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.c create mode
> 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_hwseq.h create
> mode 100644 drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/hwss/dcn60/dcn60_init.h create mode
> 100644 drivers/gpu/drm/amd/display/dc/irq/dcn60/irq_service_dcn60.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/irq/dcn60/irq_service_dcn60.h create
> mode
> 100644 drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.c create
> mode
> 100644 drivers/gpu/drm/amd/display/dc/mpc/dcn60/dcn60_mpc.h create
> mode
> 100644 drivers/gpu/drm/amd/display/dc/opp/dcn60/dcn60_opp.c create
> mode
> 100644 drivers/gpu/drm/amd/display/dc/opp/dcn60/dcn60_opp.h create
> mode
> 100644 drivers/gpu/drm/amd/display/dc/optc/dcn60/dcn60_optc.c create
> mode
> 100644 drivers/gpu/drm/amd/display/dc/optc/dcn60/dcn60_optc.h create
> mode
> 100644 drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.c
> create mode 100644
> drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.h create
> mode
> 100644
> drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn60/dcn60_soc_a
> nd_ip
> _translator.c create mode 100644
> drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn60/dcn60_soc_a
> nd_ip
> _translator.h create mode 100644
> drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.c create mode 100644
> drivers/gpu/drm/amd/display/dmub/src/dmub_dcn60.h create mode 100644
> drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_6_0_0_offset.h create
> mode
> 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_6_0_0_sh_mask.h
> create mode 100644
> drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_6_0_0_offset.h
> create mode 100644
> drivers/gpu/drm/amd/include/asic_reg/dpcs/dpcs_6_0_0_sh_mask.h create
> mode
> 100644 drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_5_0_1_offset.h
> create mode 100644
> drivers/gpu/drm/amd/include/asic_reg/mmhub/mmhub_5_0_1_sh_mask.h
>
> --
> 2.34.1





^ permalink raw reply	[flat|nested] 43+ messages in thread

end of thread, other threads:[~2026-08-05 20:03 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-31 21:12 [PATCH 00/41] DC Patches July 31, 2026 Roman.Li
2026-07-31 21:12 ` [PATCH 03/41] drm/amd/display: Enable DCN6 init Roman.Li
2026-07-31 21:12 ` [PATCH 04/41] drm/amd/display: Dependent changes for DCN6 Roman.Li
2026-07-31 21:12 ` [PATCH 05/41] drm/amd/display: Enable DCN6 sources compilation Roman.Li
2026-07-31 21:12 ` [PATCH 06/41] drm/amd/display: Remove duplicate in tests/Makefile Roman.Li
2026-07-31 21:12 ` [PATCH 07/41] drm/amd/display: Resize MST HDCP per-connector arrays to 32 Roman.Li
2026-07-31 21:12 ` [PATCH 08/41] drm/amd/display: Bounds-check connector->index in dm_dp_mst_get_modes Roman.Li
2026-07-31 21:12 ` [PATCH 09/41] drm/amd/display: Ensure dtbclk is enabled Roman.Li
2026-07-31 21:12 ` [PATCH 10/41] drm/amd/display: Update VRR info packet to support 12-bit refresh rates Roman.Li
2026-07-31 21:12 ` [PATCH 11/41] drm/amd/display: Gate HDMI FRL status polling on active FRL link rate Roman.Li
2026-07-31 21:12 ` [PATCH 12/41] drm/amd/display: Fix wb_info leak and NULL deref in writeback Roman.Li
2026-07-31 21:12 ` [PATCH 13/41] drm/amd/display: Fix seamless mode switch not triggering for HDR to SDR transition Roman.Li
2026-07-31 21:12 ` [PATCH 14/41] drm/amd/display: Add KUnit tests for more crtc functions Roman.Li
2026-07-31 21:12 ` [PATCH 15/41] drm/amd/display: Add vblank handling tests for crtc Roman.Li
2026-07-31 21:12 ` [PATCH 16/41] drm/amd/display: Add idle worker " Roman.Li
2026-07-31 21:12 ` [PATCH 17/41] drm/amd/display: Add active plane count " Roman.Li
2026-07-31 21:12 ` [PATCH 18/41] drm/amd/display: Add KUnit test for crtc vblank event completion Roman.Li
2026-07-31 21:12 ` [PATCH 19/41] drm/amd/display: Add KUnit tests for crtc set_vupdate_irq Roman.Li
2026-07-31 21:12 ` [PATCH 20/41] drm/amd/display: Add KUnit tests for crtc set_static_screen_optimze Roman.Li
2026-07-31 21:12 ` [PATCH 21/41] drm/amd/display: Refactor stream validation Roman.Li
2026-07-31 21:12 ` [PATCH 22/41] drm/amd/display: Unify force_yuv debugfs into force_yuv_pixel_format Roman.Li
2026-07-31 21:12 ` [PATCH 23/41] drm/amd/display: Align connector KUnit tests with stream validation refactor Roman.Li
2026-07-31 21:12 ` [PATCH 24/41] drm/amd/display: Increase fclk change latency on dcn351 Roman.Li
2026-07-31 21:12 ` [PATCH 25/41] drm/amd/display: Add KUnit tests for crtc set_vblank Roman.Li
2026-07-31 21:12 ` [PATCH 26/41] drm/amd/display: Cover crtc set_vblank workqueue branch Roman.Li
2026-07-31 21:12 ` [PATCH 27/41] drm/amd/display: Cover crtc vblank IPS self-refresh restore Roman.Li
2026-07-31 21:12 ` [PATCH 28/41] drm/amd/display: Cover crtc vblank restore replay-supported path Roman.Li
2026-07-31 21:12 ` [PATCH 29/41] drm/amd/display: Cover crtc destroy_state stream release Roman.Li
2026-07-31 21:12 ` [PATCH 30/41] drm/amd/display: Fix ABM over VABC Roman.Li
2026-07-31 21:12 ` [PATCH 31/41] drm/amd/display: Add missing DCN42B register defines Roman.Li
2026-07-31 21:12 ` [PATCH 32/41] drm/amd/display: Add missing DMUB CACP and PR definitions Roman.Li
2026-07-31 21:12 ` [PATCH 33/41] drm/amd/display: Add missing OTG_CRC1_SELECT mask for DCN3.2 Roman.Li
2026-07-31 21:12 ` [PATCH 34/41] drm/amd/display: Fix CRC engine 1 enable/disable on DCN3.1.2+ Roman.Li
2026-07-31 21:12 ` [PATCH 35/41] drm/amd/display: Configure all CRC engines in pipe CRC source path Roman.Li
2026-07-31 21:12 ` [PATCH 36/41] drm/amd/display: Fix more KUnit connector use-after-free bugs Roman.Li
2026-07-31 21:12 ` [PATCH 37/41] drm/amd/display: Update BW bounding box unconditionally for DCN6 Roman.Li
2026-07-31 21:12 ` [PATCH 38/41] drm/amd/display: switch max FFE level cap based on FRL link rate Roman.Li
2026-07-31 21:13 ` [PATCH 39/41] drm/amd/display: Add FFE level defaults Roman.Li
2026-07-31 21:13 ` [PATCH 40/41] drm/amd/display: Migrate color manager HW and fix MCM blend LUT issues Roman.Li
2026-07-31 21:13 ` [PATCH 41/41] drm/amd/display: Promote DC to 3.2.392 Roman.Li
2026-08-04 13:24 ` [PATCH 00/41] DC Patches July 31, 2026 Wheeler, Daniel
2026-08-04 21:15   ` Timur Kristóf
2026-08-05 20:03     ` Wheeler, Daniel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.