summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/display
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/Makefile3
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c384
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h21
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c27
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c7
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h1
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c90
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.h6
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c52
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c9
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c598
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h151
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c36
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h63
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c6
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c25
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h17
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/vector.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser.c42
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/command_table.c124
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/command_table2.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/command_table_helper2.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile23
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c35
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c64
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c166
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c1183
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h86
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.c431
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.h190
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c434
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c61
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_state.c77
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_surface.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h92
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_bios_types.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c38
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dp_types.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_helper.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_hw_types.h79
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_plane.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_spl_translate.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_trace.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_types.h40
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/Makefile11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn20/dcn20_dccg.h16
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c28
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c334
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h273
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_abm.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_abm.h60
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_audio.c134
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_audio.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c966
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c65
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_opp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_transform.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c18
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.h31
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/Makefile11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c205
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.h140
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c522
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.h206
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c65
-rw-r--r--drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c111
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c23
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c29
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn351/dcn351_fpu.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/Makefile73
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/display_mode_core.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.c63
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.c215
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c387
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h30
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c381
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.h60
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42_soc_bb.h263
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_display_cfg_types.h13
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_soc_parameter_types.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/dml_top_types.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c112
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.c54
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.c63
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c53
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c79
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.h12
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_legacy.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/inc/dml2_internal_shared_types.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c36
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c44
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c26
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/Makefile10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c27
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c333
-rw-r--r--drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h469
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dsc.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/Makefile13
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.c254
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.h31
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c206
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.h36
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/hpo/Makefile11
-rw-r--r--drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.h10
-rw-r--r--drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.c93
-rw-r--r--drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.h17
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/Makefile10
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c576
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.h268
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/Makefile10
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.c211
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn401/dcn401_hubp.h23
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c742
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h79
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/Makefile12
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce/dce_hwseq.h13
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c168
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c55
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn31/dcn31_hwseq.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c18
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c455
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c1104
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h47
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c173
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.h11
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h23
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer_private.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/core_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h24
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h102
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h10
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h36
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h20
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h100
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/transform.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/resource.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/Makefile9
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c415
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.h15
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_detection.c72
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_dpms.c640
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_factory.c29
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_validation.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c36
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c25
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/mmhubbub/Makefile10
-rw-r--r--drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.c25
-rw-r--r--drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.h13
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/Makefile10
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn10/dcn10_mpc.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.c190
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn401/dcn401_mpc.h35
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c797
-rw-r--r--drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h962
-rw-r--r--drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/Makefile10
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h26
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c291
-rw-r--r--drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h220
-rw-r--r--drivers/gpu/drm/amd/display/dc/pg/Makefile10
-rw-r--r--drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c649
-rw-r--r--drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h175
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/Makefile18
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c29
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn201/dcn201_resource.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.c36
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn301/dcn301_resource.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c18
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c18
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn36/dcn36_resource.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c43
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c2358
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h591
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.c47
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.h (renamed from drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.h)17
-rw-r--r--drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/Makefile3
-rw-r--r--drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c172
-rw-r--r--drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/soc_and_ip_translator.c4
-rw-r--r--drivers/gpu/drm/amd/display/dmub/dmub_srv.h5
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h127
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/Makefile3
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c20
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c1
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c23
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c17
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c18
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c22
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c759
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h303
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c4
-rw-r--r--drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c72
-rw-r--r--drivers/gpu/drm/amd/display/include/bios_parser_types.h2
-rw-r--r--drivers/gpu/drm/amd/display/include/dal_asic_id.h1
-rw-r--r--drivers/gpu/drm/amd/display/include/dal_types.h1
-rw-r--r--drivers/gpu/drm/amd/display/include/dpcd_defs.h3
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.c2
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c6
-rw-r--r--drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h1
384 files changed, 22233 insertions, 3971 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
index 8e949fe77312..89350aa9ca7e 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/Makefile
@@ -40,7 +40,8 @@ AMDGPUDM = \
amdgpu_dm_replay.o \
amdgpu_dm_quirks.o \
amdgpu_dm_wb.o \
- amdgpu_dm_colorop.o
+ amdgpu_dm_colorop.o \
+ amdgpu_dm_ism.o
ifdef CONFIG_DRM_AMD_DC_FP
AMDGPUDM += dc_fpu.o
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 2328c1aa0ead..21635e80349a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
/*
- * Copyright 2015 Advanced Micro Devices, Inc.
+ * Copyright 2015-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -91,6 +91,7 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_edid.h>
#include <drm/drm_eld.h>
+#include <drm/drm_mode.h>
#include <drm/drm_utils.h>
#include <drm/drm_vblank.h>
#include <drm/drm_audio_component.h>
@@ -152,6 +153,9 @@ MODULE_FIRMWARE(FIRMWARE_DCN_36_DMUB);
#define FIRMWARE_DCN_401_DMUB "amdgpu/dcn_4_0_1_dmcub.bin"
MODULE_FIRMWARE(FIRMWARE_DCN_401_DMUB);
+#define FIRMWARE_DCN_42_DMUB "amdgpu/dcn_4_2_dmcub.bin"
+MODULE_FIRMWARE(FIRMWARE_DCN_42_DMUB);
+
/**
* DOC: overview
*
@@ -1368,6 +1372,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
case IP_VERSION(3, 5, 0):
case IP_VERSION(3, 5, 1):
case IP_VERSION(3, 6, 0):
+ case IP_VERSION(4, 2, 0):
hw_params.ips_sequential_ono = adev->external_rev_id > 0x10;
hw_params.lower_hbr3_phy_ssc = true;
break;
@@ -1815,6 +1820,9 @@ static void *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev)
case IP_VERSION(4, 0, 1):
bb_size = sizeof(struct dml2_soc_bb);
break;
+ case IP_VERSION(4, 2, 0):
+ bb_size = sizeof(struct dml2_soc_bb);
+ break;
default:
return NULL;
}
@@ -1859,6 +1867,9 @@ static enum dmub_ips_disable_type dm_get_default_ips_mode(
case IP_VERSION(3, 5, 1):
ret = DMUB_IPS_RCG_IN_ACTIVE_IPS2_IN_OFF;
break;
+ case IP_VERSION(4, 2, 0):
+ ret = DMUB_IPS_DISABLE_ALL;
+ break;
default:
/* ASICs older than DCN35 do not have IPSs */
if (amdgpu_ip_version(adev, DCE_HWIP, 0) < IP_VERSION(3, 5, 0))
@@ -2002,6 +2013,13 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0))
init_data.num_virtual_links = 1;
+ /* DCN42 and above dpia switch to unified link training path */
+ if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(4, 2, 0)) {
+ init_data.flags.consolidated_dpia_dp_lt = true;
+ init_data.flags.enable_dpia_pre_training = true;
+ init_data.flags.unify_link_enc_assignment = true;
+ init_data.flags.usb4_bw_alloc_support = true;
+ }
retrieve_dmi_info(&adev->dm);
if (adev->dm.edp0_on_dp1_quirk)
init_data.flags.support_edp0_on_dp1 = true;
@@ -2272,6 +2290,11 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
&adev->dm.dmub_bo_gpu_addr,
&adev->dm.dmub_bo_cpu_addr);
+ if (adev->dm.boot_time_crc_info.bo_ptr)
+ amdgpu_bo_free_kernel(&adev->dm.boot_time_crc_info.bo_ptr,
+ &adev->dm.boot_time_crc_info.gpu_addr,
+ &adev->dm.boot_time_crc_info.cpu_addr);
+
if (adev->dm.hpd_rx_offload_wq && adev->dm.dc) {
for (i = 0; i < adev->dm.dc->caps.max_links; i++) {
if (adev->dm.hpd_rx_offload_wq[i].wq) {
@@ -2369,6 +2392,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
case IP_VERSION(3, 5, 1):
case IP_VERSION(3, 6, 0):
case IP_VERSION(4, 0, 1):
+ case IP_VERSION(4, 2, 0):
return 0;
default:
break;
@@ -2454,6 +2478,8 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_7_SCRATCH_MEM
DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_IB_MEM
DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_SHARED_STATE
+ DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_LSDMA_BUFFER
+ DMUB_WINDOW_MEMORY_TYPE_FB, //DMUB_WINDOW_CURSOR_OFFLOAD
};
int r;
@@ -2502,7 +2528,9 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
case IP_VERSION(4, 0, 1):
dmub_asic = DMUB_ASIC_DCN401;
break;
-
+ case IP_VERSION(4, 2, 0):
+ dmub_asic = DMUB_ASIC_DCN42;
+ break;
default:
/* ASIC doesn't support DMUB. */
return 0;
@@ -2715,6 +2743,54 @@ static int detect_mst_link_for_all_connectors(struct drm_device *dev)
return ret;
}
+static void amdgpu_dm_boot_time_crc_init(struct amdgpu_device *adev)
+{
+ struct dm_boot_time_crc_info *bootcrc_info = NULL;
+ struct dmub_srv *dmub = NULL;
+ union dmub_fw_boot_options option = {0};
+ int ret = 0;
+ const uint32_t fb_size = 3 * 1024 * 1024; /* 3MB for DCC pattern */
+
+ if (!adev || !adev->dm.dc || !adev->dm.dc->ctx ||
+ !adev->dm.dc->ctx->dmub_srv) {
+ return;
+ }
+
+ dmub = adev->dm.dc->ctx->dmub_srv->dmub;
+ bootcrc_info = &adev->dm.boot_time_crc_info;
+
+ if (!dmub || !dmub->hw_funcs.get_fw_boot_option) {
+ drm_dbg(adev_to_drm(adev), "failed to init boot time crc buffer\n");
+ return;
+ }
+
+ option = dmub->hw_funcs.get_fw_boot_option(dmub);
+
+ /* Return if boot time CRC is not enabled */
+ if (option.bits.bootcrc_en_at_S0i3 == 0)
+ return;
+
+ /* Create a buffer for boot time CRC */
+ ret = amdgpu_bo_create_kernel(adev, fb_size, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT,
+ &bootcrc_info->bo_ptr,
+ &bootcrc_info->gpu_addr,
+ &bootcrc_info->cpu_addr);
+
+ if (ret) {
+ drm_dbg(adev_to_drm(adev), "failed to create boot time crc buffer\n");
+ } else {
+ bootcrc_info->size = fb_size;
+
+ drm_dbg(adev_to_drm(adev), "boot time crc buffer created addr 0x%llx, size %u\n",
+ bootcrc_info->gpu_addr, bootcrc_info->size);
+
+ /* Send the buffer info to DMUB */
+ dc_dmub_srv_boot_time_crc_init(adev->dm.dc,
+ bootcrc_info->gpu_addr, bootcrc_info->size);
+ }
+}
+
static int dm_late_init(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
@@ -2726,6 +2802,11 @@ static int dm_late_init(struct amdgpu_ip_block *ip_block)
dmcu = adev->dm.dc->res_pool->dmcu;
+ /* Init the boot time CRC (skip in resume) */
+ if ((adev->in_suspend == 0) &&
+ (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(3, 6, 0)))
+ amdgpu_dm_boot_time_crc_init(adev);
+
for (i = 0; i < 16; i++)
linear_lut[i] = 0xFFFF * i / 15;
@@ -3202,6 +3283,7 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)
mutex_lock(&dm->dc_lock);
+ amdgpu_dm_ism_disable(dm);
dc_allow_idle_optimizations(adev->dm.dc, false);
dm->cached_dc_state = dc_state_create_copy(dm->dc->current_state);
@@ -3235,6 +3317,9 @@ static int dm_suspend(struct amdgpu_ip_block *ip_block)
amdgpu_dm_irq_suspend(adev);
+ scoped_guard(mutex, &dm->dc_lock)
+ amdgpu_dm_ism_disable(dm);
+
hpd_rx_irq_work_suspend(dm);
dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3);
@@ -3525,6 +3610,7 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
dc_resume(dm->dc);
+ amdgpu_dm_ism_enable(dm);
amdgpu_dm_irq_resume_early(adev);
for (i = 0; i < dc_state->stream_count; i++) {
@@ -3585,6 +3671,9 @@ static int dm_resume(struct amdgpu_ip_block *ip_block)
/* program HPD filter */
dc_resume(dm->dc);
+ scoped_guard(mutex, &dm->dc_lock)
+ amdgpu_dm_ism_enable(dm);
+
/*
* early enable HPD Rx IRQ, should be done before set mode as short
* pulse interrupts are used for MST
@@ -3765,6 +3854,10 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
caps->aux_support = false;
+ drm_object_property_set_value(&conn_base->base,
+ adev_to_drm(adev)->mode_config.panel_type_property,
+ caps->ext_caps->bits.oled ? DRM_MODE_PANEL_TYPE_OLED : DRM_MODE_PANEL_TYPE_UNKNOWN);
+
if (caps->ext_caps->bits.oled == 1
/*
* ||
@@ -4386,105 +4479,6 @@ static int register_hpd_handlers(struct amdgpu_device *adev)
return 0;
}
-#if defined(CONFIG_DRM_AMD_DC_SI)
-/* Register IRQ sources and initialize IRQ callbacks */
-static int dce60_register_irq_handlers(struct amdgpu_device *adev)
-{
- struct dc *dc = adev->dm.dc;
- struct common_irq_params *c_irq_params;
- struct dc_interrupt_params int_params = {0};
- int r;
- int i;
- unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
-
- int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
- int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
-
- /*
- * Actions of amdgpu_irq_add_id():
- * 1. Register a set() function with base driver.
- * Base driver will call set() function to enable/disable an
- * interrupt in DC hardware.
- * 2. Register amdgpu_dm_irq_handler().
- * Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
- * coming from DC hardware.
- * amdgpu_dm_irq_handler() will re-direct the interrupt to DC
- * for acknowledging and handling.
- */
-
- /* Use VBLANK interrupt */
- for (i = 0; i < adev->mode_info.num_crtc; i++) {
- r = amdgpu_irq_add_id(adev, client_id, i + 1, &adev->crtc_irq);
- if (r) {
- drm_err(adev_to_drm(adev), "Failed to add crtc irq id!\n");
- return r;
- }
-
- int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
- int_params.irq_source =
- dc_interrupt_to_irq_source(dc, i + 1, 0);
-
- if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
- int_params.irq_source < DC_IRQ_SOURCE_VBLANK1 ||
- int_params.irq_source > DC_IRQ_SOURCE_VBLANK6) {
- drm_err(adev_to_drm(adev), "Failed to register vblank irq!\n");
- return -EINVAL;
- }
-
- c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1];
-
- c_irq_params->adev = adev;
- c_irq_params->irq_src = int_params.irq_source;
-
- if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
- dm_crtc_high_irq, c_irq_params))
- return -ENOMEM;
- }
-
- /* Use GRPH_PFLIP interrupt */
- for (i = VISLANDS30_IV_SRCID_D1_GRPH_PFLIP;
- i <= VISLANDS30_IV_SRCID_D6_GRPH_PFLIP; i += 2) {
- r = amdgpu_irq_add_id(adev, client_id, i, &adev->pageflip_irq);
- if (r) {
- drm_err(adev_to_drm(adev), "Failed to add page flip irq id!\n");
- return r;
- }
-
- int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
- int_params.irq_source =
- dc_interrupt_to_irq_source(dc, i, 0);
-
- if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
- int_params.irq_source < DC_IRQ_SOURCE_PFLIP_FIRST ||
- int_params.irq_source > DC_IRQ_SOURCE_PFLIP_LAST) {
- drm_err(adev_to_drm(adev), "Failed to register pflip irq!\n");
- return -EINVAL;
- }
-
- c_irq_params = &adev->dm.pflip_params[int_params.irq_source - DC_IRQ_SOURCE_PFLIP_FIRST];
-
- c_irq_params->adev = adev;
- c_irq_params->irq_src = int_params.irq_source;
-
- if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
- dm_pflip_high_irq, c_irq_params))
- return -ENOMEM;
- }
-
- /* HPD */
- r = amdgpu_irq_add_id(adev, client_id,
- VISLANDS30_IV_SRCID_HOTPLUG_DETECT_A, &adev->hpd_irq);
- if (r) {
- drm_err(adev_to_drm(adev), "Failed to add hpd irq id!\n");
- return r;
- }
-
- r = register_hpd_handlers(adev);
-
- return r;
-}
-#endif
-
/* Register IRQ sources and initialize IRQ callbacks */
static int dce110_register_irq_handlers(struct amdgpu_device *adev)
{
@@ -4493,7 +4487,12 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
struct dc_interrupt_params int_params = {0};
int r;
int i;
+ unsigned int src_id;
unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
+ /* Use different interrupts for VBLANK on DCE 6 vs. newer. */
+ const unsigned int vblank_d1 =
+ adev->dm.dc->ctx->dce_version >= DCE_VERSION_8_0
+ ? VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0 : 1;
if (adev->family >= AMDGPU_FAMILY_AI)
client_id = SOC15_IH_CLIENTID_DCE;
@@ -4514,8 +4513,9 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
*/
/* Use VBLANK interrupt */
- for (i = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0; i <= VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0; i++) {
- r = amdgpu_irq_add_id(adev, client_id, i, &adev->crtc_irq);
+ for (i = 0; i < adev->mode_info.num_crtc; i++) {
+ src_id = vblank_d1 + i;
+ r = amdgpu_irq_add_id(adev, client_id, src_id, &adev->crtc_irq);
if (r) {
drm_err(adev_to_drm(adev), "Failed to add crtc irq id!\n");
return r;
@@ -4523,7 +4523,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
int_params.irq_source =
- dc_interrupt_to_irq_source(dc, i, 0);
+ dc_interrupt_to_irq_source(dc, src_id, 0);
if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
int_params.irq_source < DC_IRQ_SOURCE_VBLANK1 ||
@@ -4542,33 +4542,36 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
return -ENOMEM;
}
- /* Use VUPDATE interrupt */
- for (i = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT; i <= VISLANDS30_IV_SRCID_D6_V_UPDATE_INT; i += 2) {
- r = amdgpu_irq_add_id(adev, client_id, i, &adev->vupdate_irq);
- if (r) {
- drm_err(adev_to_drm(adev), "Failed to add vupdate irq id!\n");
- return r;
- }
-
- int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
- int_params.irq_source =
- dc_interrupt_to_irq_source(dc, i, 0);
+ if (dc_supports_vrr(adev->dm.dc->ctx->dce_version)) {
+ /* Use VUPDATE interrupt */
+ for (i = 0; i < adev->mode_info.num_crtc; i++) {
+ src_id = VISLANDS30_IV_SRCID_D1_V_UPDATE_INT + i * 2;
+ r = amdgpu_irq_add_id(adev, client_id, src_id, &adev->vupdate_irq);
+ if (r) {
+ drm_err(adev_to_drm(adev), "Failed to add vupdate irq id!\n");
+ return r;
+ }
- if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
- int_params.irq_source < DC_IRQ_SOURCE_VUPDATE1 ||
- int_params.irq_source > DC_IRQ_SOURCE_VUPDATE6) {
- drm_err(adev_to_drm(adev), "Failed to register vupdate irq!\n");
- return -EINVAL;
- }
+ int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
+ int_params.irq_source =
+ dc_interrupt_to_irq_source(dc, src_id, 0);
- c_irq_params = &adev->dm.vupdate_params[int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1];
+ if (int_params.irq_source == DC_IRQ_SOURCE_INVALID ||
+ int_params.irq_source < DC_IRQ_SOURCE_VUPDATE1 ||
+ int_params.irq_source > DC_IRQ_SOURCE_VUPDATE6) {
+ drm_err(adev_to_drm(adev), "Failed to register vupdate irq!\n");
+ return -EINVAL;
+ }
- c_irq_params->adev = adev;
- c_irq_params->irq_src = int_params.irq_source;
+ c_irq_params = &adev->dm.vupdate_params[
+ int_params.irq_source - DC_IRQ_SOURCE_VUPDATE1];
+ c_irq_params->adev = adev;
+ c_irq_params->irq_src = int_params.irq_source;
- if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
- dm_vupdate_high_irq, c_irq_params))
- return -ENOMEM;
+ if (!amdgpu_dm_irq_register_interrupt(adev, &int_params,
+ dm_vupdate_high_irq, c_irq_params))
+ return -ENOMEM;
+ }
}
/* Use GRPH_PFLIP interrupt */
@@ -4910,14 +4913,37 @@ static void dm_atomic_destroy_state(struct drm_private_obj *obj,
kfree(dm_state);
}
+static struct drm_private_state *
+dm_atomic_create_state(struct drm_private_obj *obj)
+{
+ struct amdgpu_device *adev = drm_to_adev(obj->dev);
+ struct dm_atomic_state *dm_state;
+ struct dc_state *context;
+
+ dm_state = kzalloc_obj(*dm_state);
+ if (!dm_state)
+ return ERR_PTR(-ENOMEM);
+
+ context = dc_state_create_current_copy(adev->dm.dc);
+ if (!context) {
+ kfree(dm_state);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ __drm_atomic_helper_private_obj_create_state(obj, &dm_state->base);
+ dm_state->context = context;
+
+ return &dm_state->base;
+}
+
static struct drm_private_state_funcs dm_atomic_state_funcs = {
+ .atomic_create_state = dm_atomic_create_state,
.atomic_duplicate_state = dm_atomic_duplicate_state,
.atomic_destroy_state = dm_atomic_destroy_state,
};
static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
{
- struct dm_atomic_state *state;
int r;
adev->mode_info.mode_config_initialized = true;
@@ -4937,42 +4963,22 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
/* indicates support for immediate flip */
adev_to_drm(adev)->mode_config.async_page_flip = true;
- state = kzalloc_obj(*state);
- if (!state)
- return -ENOMEM;
-
- state->context = dc_state_create_current_copy(adev->dm.dc);
- if (!state->context) {
- kfree(state);
- return -ENOMEM;
- }
-
drm_atomic_private_obj_init(adev_to_drm(adev),
&adev->dm.atomic_obj,
- &state->base,
&dm_atomic_state_funcs);
r = amdgpu_display_modeset_create_props(adev);
- if (r) {
- dc_state_release(state->context);
- kfree(state);
+ if (r)
return r;
- }
#ifdef AMD_PRIVATE_COLOR
- if (amdgpu_dm_create_color_properties(adev)) {
- dc_state_release(state->context);
- kfree(state);
+ if (amdgpu_dm_create_color_properties(adev))
return -ENOMEM;
- }
#endif
r = amdgpu_dm_audio_init(adev);
- if (r) {
- dc_state_release(state->context);
- kfree(state);
+ if (r)
return r;
- }
return 0;
}
@@ -5540,6 +5546,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
case IP_VERSION(3, 5, 1):
case IP_VERSION(3, 6, 0):
case IP_VERSION(4, 0, 1):
+ case IP_VERSION(4, 2, 0):
if (register_outbox_irq_handlers(dm->adev)) {
drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n");
goto fail;
@@ -5564,6 +5571,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
case IP_VERSION(3, 5, 1):
case IP_VERSION(3, 6, 0):
case IP_VERSION(4, 0, 1):
+ case IP_VERSION(4, 2, 0):
psr_feature_enabled = true;
break;
default:
@@ -5581,6 +5589,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
case IP_VERSION(3, 5, 0):
case IP_VERSION(3, 5, 1):
case IP_VERSION(3, 6, 0):
+ case IP_VERSION(4, 2, 0):
replay_feature_enabled = true;
break;
@@ -5696,11 +5705,6 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
case CHIP_PITCAIRN:
case CHIP_VERDE:
case CHIP_OLAND:
- if (dce60_register_irq_handlers(dm->adev)) {
- drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n");
- goto fail;
- }
- break;
#endif
case CHIP_BONAIRE:
case CHIP_HAWAII:
@@ -5746,6 +5750,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
case IP_VERSION(3, 5, 1):
case IP_VERSION(3, 6, 0):
case IP_VERSION(4, 0, 1):
+ case IP_VERSION(4, 2, 0):
if (dcn10_register_irq_handlers(dm->adev)) {
drm_err(adev_to_drm(adev), "DM: Failed to initialize IRQ\n");
goto fail;
@@ -5894,6 +5899,9 @@ static int dm_init_microcode(struct amdgpu_device *adev)
case IP_VERSION(4, 0, 1):
fw_name_dmub = FIRMWARE_DCN_401_DMUB;
break;
+ case IP_VERSION(4, 2, 0):
+ fw_name_dmub = FIRMWARE_DCN_42_DMUB;
+ break;
default:
/* ASIC doesn't support DMUB. */
return 0;
@@ -6021,6 +6029,7 @@ static int dm_early_init(struct amdgpu_ip_block *ip_block)
case IP_VERSION(3, 5, 1):
case IP_VERSION(3, 6, 0):
case IP_VERSION(4, 0, 1):
+ case IP_VERSION(4, 2, 0):
adev->mode_info.num_crtc = 4;
adev->mode_info.num_hpd = 4;
adev->mode_info.num_dig = 4;
@@ -6037,8 +6046,8 @@ static int dm_early_init(struct amdgpu_ip_block *ip_block)
adev->mode_info.funcs = &dm_display_funcs;
/*
- * Note: Do NOT change adev->audio_endpt_rreg and
- * adev->audio_endpt_wreg because they are initialised in
+ * Note: Do NOT change adev->reg.audio_endpt.rreg and
+ * adev->reg.audio_endpt.wreg because they are initialised in
* amdgpu_device_init()
*/
#if defined(CONFIG_DEBUG_KERNEL_DC)
@@ -6721,11 +6730,11 @@ static void fill_stream_properties_from_drm_display_mode(
&& aconnector
&& aconnector->force_yuv420_output)
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
- else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR422)
+ else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
&& aconnector
&& aconnector->force_yuv422_output)
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR422;
- else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR444)
+ else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR444))
&& stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
else
@@ -8579,6 +8588,12 @@ static int to_drm_connector_type(enum signal_type st, uint32_t connector_id)
return DRM_MODE_CONNECTOR_VGA;
case SIGNAL_TYPE_DISPLAY_PORT:
case SIGNAL_TYPE_DISPLAY_PORT_MST:
+ /* External DP bridges have a different connector type. */
+ if (connector_id == CONNECTOR_ID_VGA)
+ return DRM_MODE_CONNECTOR_VGA;
+ else if (connector_id == CONNECTOR_ID_LVDS)
+ return DRM_MODE_CONNECTOR_LVDS;
+
return DRM_MODE_CONNECTOR_DisplayPort;
case SIGNAL_TYPE_DVI_DUAL_LINK:
case SIGNAL_TYPE_DVI_SINGLE_LINK:
@@ -9074,6 +9089,8 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
if (connector_type == DRM_MODE_CONNECTOR_eDP) {
struct drm_privacy_screen *privacy_screen;
+ drm_connector_attach_panel_type_property(&aconnector->base);
+
privacy_screen = drm_privacy_screen_get(adev_to_drm(adev)->dev, NULL);
if (!IS_ERR(privacy_screen)) {
drm_connector_attach_privacy_screen_provider(&aconnector->base,
@@ -9251,8 +9268,7 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
connector_type == DRM_MODE_CONNECTOR_HDMIB)
amdgpu_dm_initialize_hdmi_connector(aconnector);
- if (connector_type == DRM_MODE_CONNECTOR_DisplayPort
- || connector_type == DRM_MODE_CONNECTOR_eDP)
+ if (dc_is_dp_signal(link->connector_signal))
amdgpu_dm_initialize_dp_connector(dm, aconnector, link->link_index);
out_free:
@@ -9326,31 +9342,7 @@ static void manage_dm_interrupts(struct amdgpu_device *adev,
if (acrtc_state) {
timing = &acrtc_state->stream->timing;
- /*
- * Depending on when the HW latching event of double-buffered
- * registers happen relative to the PSR SDP deadline, and how
- * bad the Panel clock has drifted since the last ALPM off
- * event, there can be up to 3 frames of delay between sending
- * the PSR exit cmd to DMUB fw, and when the panel starts
- * displaying live frames.
- *
- * We can set:
- *
- * 20/100 * offdelay_ms = 3_frames_ms
- * => offdelay_ms = 5 * 3_frames_ms
- *
- * This ensures that `3_frames_ms` will only be experienced as a
- * 20% delay on top how long the display has been static, and
- * thus make the delay less perceivable.
- */
- if (acrtc_state->stream->link->psr_settings.psr_version <
- DC_PSR_VERSION_UNSUPPORTED) {
- offdelay = DIV64_U64_ROUND_UP((u64)5 * 3 * 10 *
- timing->v_total *
- timing->h_total,
- timing->pix_clk_100hz);
- config.offdelay_ms = offdelay ?: 30;
- } else if (amdgpu_ip_version(adev, DCE_HWIP, 0) <
+ if (amdgpu_ip_version(adev, DCE_HWIP, 0) <
IP_VERSION(3, 5, 0) ||
!(adev->flags & AMD_IS_APU)) {
/*
@@ -9895,7 +9887,8 @@ static void amdgpu_dm_enable_self_refresh(struct amdgpu_crtc *acrtc_attach,
* a vblank event disable request to enable PSR/RP. PSR SU/RP
* can be enabled immediately once OS demonstrates an
* adequate number of fast atomic commits to notify KMD
- * of update events. See `vblank_control_worker()`.
+ * of update events.
+ * See `amdgpu_dm_crtc_vblank_control_worker()`.
*/
if (!vrr_active &&
acrtc_attach->dm_irq_params.allow_sr_entry &&
@@ -10063,8 +10056,9 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
/*
* If the dirty regions changed, PSR-SU need to be disabled temporarily
* and enabled it again after dirty regions are stable to avoid video glitch.
- * PSR-SU will be enabled in vblank_control_worker() if user pause the video
- * during the PSR-SU was disabled.
+ * PSR-SU will be enabled in
+ * amdgpu_dm_crtc_vblank_control_worker() if user
+ * pause the video during the PSR-SU was disabled.
*/
if (acrtc_state->stream->link->psr_settings.psr_version >= DC_PSR_VERSION_SU_1 &&
acrtc_attach->dm_irq_params.allow_sr_entry &&
@@ -12314,10 +12308,11 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev,
int i;
/* Overlay cursor not supported on HW before DCN
- * DCN401 does not have the cursor-on-scaled-plane or cursor-on-yuv-plane restrictions
- * as previous DCN generations, so enable native mode on DCN401
+ * DCN401/420 does not have the cursor-on-scaled-plane or cursor-on-yuv-plane restrictions
+ * as previous DCN generations, so enable native mode on DCN401/420
*/
- if (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1)) {
+ if (amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 0, 1) ||
+ amdgpu_ip_version(adev, DCE_HWIP, 0) == IP_VERSION(4, 2, 0)) {
*cursor_mode = DM_CURSOR_NATIVE_MODE;
return 0;
}
@@ -12742,7 +12737,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
/* 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, 0, 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))) {
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.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index d15812d51d72..d1a14e0c12bd 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -123,6 +123,20 @@ struct dm_compressor_info {
uint64_t gpu_addr;
};
+/**
+ * struct dm_boot_time_crc_info - Buffer info used by boot time CRC
+ * @cpu_addr: MMIO cpu addr
+ * @bo_ptr: Pointer to the buffer object
+ * @gpu_addr: MMIO gpu addr
+ * @size: Size of the buffer
+ */
+struct dm_boot_time_crc_info {
+ void *cpu_addr;
+ struct amdgpu_bo *bo_ptr;
+ uint64_t gpu_addr;
+ uint32_t size;
+};
+
typedef void (*dmub_notify_interrupt_callback_t)(struct amdgpu_device *adev, struct dmub_notification *notify);
/**
@@ -698,6 +712,13 @@ struct amdgpu_display_manager {
struct completion replied;
char reply_data[0x40]; // Cannot include dmub_cmd here
} fused_io[8];
+
+ /**
+ * @dm_boot_time_crc_info:
+ *
+ * Buffer info for the boot time crc.
+ */
+ struct dm_boot_time_crc_info boot_time_crc_info;
};
enum dsc_clock_force_state {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
index aa4658867e55..7ee051cb3c05 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_colorop.c
@@ -55,6 +55,10 @@ const u64 amdgpu_dm_supported_blnd_tfs =
#define LUT3D_SIZE 17
+static const struct drm_colorop_funcs dm_colorop_funcs = {
+ .destroy = drm_colorop_destroy,
+};
+
int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_prop_enum_list *list)
{
struct drm_colorop *ops[MAX_COLOR_PIPELINE_OPS];
@@ -73,7 +77,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
}
- ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane,
+ ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, &dm_colorop_funcs,
amdgpu_dm_supported_degam_tfs,
DRM_COLOROP_FLAG_ALLOW_BYPASS);
if (ret)
@@ -90,7 +94,8 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
}
- ret = drm_plane_colorop_mult_init(dev, ops[i], plane, DRM_COLOROP_FLAG_ALLOW_BYPASS);
+ ret = drm_plane_colorop_mult_init(dev, ops[i], plane, &dm_colorop_funcs,
+ DRM_COLOROP_FLAG_ALLOW_BYPASS);
if (ret)
goto cleanup;
@@ -105,7 +110,9 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
}
- ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane, DRM_COLOROP_FLAG_ALLOW_BYPASS);
+ ret = drm_plane_colorop_ctm_3x4_init(dev, ops[i], plane,
+ &dm_colorop_funcs,
+ DRM_COLOROP_FLAG_ALLOW_BYPASS);
if (ret)
goto cleanup;
@@ -121,7 +128,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
}
- ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane,
+ ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, &dm_colorop_funcs,
amdgpu_dm_supported_shaper_tfs,
DRM_COLOROP_FLAG_ALLOW_BYPASS);
if (ret)
@@ -138,7 +145,9 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
}
- ret = drm_plane_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES,
+ ret = drm_plane_colorop_curve_1d_lut_init(dev, ops[i], plane,
+ &dm_colorop_funcs,
+ MAX_COLOR_LUT_ENTRIES,
DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR,
DRM_COLOROP_FLAG_ALLOW_BYPASS);
if (ret)
@@ -155,7 +164,8 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
}
- ret = drm_plane_colorop_3dlut_init(dev, ops[i], plane, LUT3D_SIZE,
+ ret = drm_plane_colorop_3dlut_init(dev, ops[i], plane,
+ &dm_colorop_funcs, LUT3D_SIZE,
DRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL,
DRM_COLOROP_FLAG_ALLOW_BYPASS);
if (ret)
@@ -173,7 +183,7 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
}
- ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane,
+ ret = drm_plane_colorop_curve_1d_init(dev, ops[i], plane, &dm_colorop_funcs,
amdgpu_dm_supported_blnd_tfs,
DRM_COLOROP_FLAG_ALLOW_BYPASS);
if (ret)
@@ -190,7 +200,8 @@ int amdgpu_dm_initialize_default_pipeline(struct drm_plane *plane, struct drm_pr
goto cleanup;
}
- ret = drm_plane_colorop_curve_1d_lut_init(dev, ops[i], plane, MAX_COLOR_LUT_ENTRIES,
+ ret = drm_plane_colorop_curve_1d_lut_init(dev, ops[i], plane, &dm_colorop_funcs,
+ MAX_COLOR_LUT_ENTRIES,
DRM_COLOROP_LUT1D_INTERPOLATION_LINEAR,
DRM_COLOROP_FLAG_ALLOW_BYPASS);
if (ret)
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 b96fbc03c371..62573173e2ac 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
@@ -812,7 +812,6 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
unsigned long flags1;
bool forward_roi_change = false;
bool notify_ta = false;
- bool all_crc_ready = true;
struct dc_stream_state *stream_state;
int i;
@@ -936,9 +935,6 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
continue;
}
- if (!crtc_ctx->crc_info.crc[i].crc_ready)
- all_crc_ready = false;
-
if (reset_crc_frame_count[i] || crtc_ctx->crc_info.crc[i].frame_count == UINT_MAX)
/* Reset the reference frame count after user update the ROI
* or it reaches the maximum value.
@@ -948,9 +944,6 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
crtc_ctx->crc_info.crc[i].frame_count += 1;
}
spin_unlock_irqrestore(&crtc_ctx->crc_info.lock, flags1);
-
- if (all_crc_ready)
- complete_all(&crtc_ctx->crc_info.completion);
}
void amdgpu_dm_crtc_secure_display_create_contexts(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
index 95bdb8699d7f..8538513ea879 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h
@@ -70,7 +70,6 @@ struct crc_data {
struct crc_info {
struct crc_data crc[MAX_CRC_WINDOW_NUM];
- struct completion completion;
spinlock_t lock;
};
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 304437c2284d..c3c588294665 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
@@ -124,37 +124,37 @@ bool amdgpu_dm_crtc_vrr_active(const struct dm_crtc_state *dm_state)
* - Enable condition same as above
* - Disable when vblank counter is enabled
*/
-static void amdgpu_dm_crtc_set_panel_sr_feature(
- struct vblank_control_work *vblank_work,
+void amdgpu_dm_crtc_set_panel_sr_feature(
+ struct amdgpu_display_manager *dm,
+ struct amdgpu_crtc *acrtc,
+ struct dc_stream_state *stream,
bool vblank_enabled, bool allow_sr_entry)
{
- struct dc_link *link = vblank_work->stream->link;
+ struct dc_link *link = stream->link;
bool is_sr_active = (link->replay_settings.replay_allow_active ||
link->psr_settings.psr_allow_active);
bool is_crc_window_active = false;
- bool vrr_active = amdgpu_dm_crtc_vrr_active_irq(vblank_work->acrtc);
+ bool vrr_active = amdgpu_dm_crtc_vrr_active_irq(acrtc);
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
is_crc_window_active =
- amdgpu_dm_crc_window_is_activated(&vblank_work->acrtc->base);
+ amdgpu_dm_crc_window_is_activated(&acrtc->base);
#endif
if (link->replay_settings.replay_feature_enabled && !vrr_active &&
allow_sr_entry && !is_sr_active && !is_crc_window_active) {
- amdgpu_dm_replay_enable(vblank_work->stream, true);
+ amdgpu_dm_replay_enable(stream, true);
} else if (vblank_enabled) {
if (link->psr_settings.psr_version < DC_PSR_VERSION_SU_1 && is_sr_active)
- amdgpu_dm_psr_disable(vblank_work->stream, false);
+ amdgpu_dm_psr_disable(stream, false);
} else if (link->psr_settings.psr_feature_enabled && !vrr_active &&
allow_sr_entry && !is_sr_active && !is_crc_window_active) {
struct amdgpu_dm_connector *aconn =
- (struct amdgpu_dm_connector *) vblank_work->stream->dm_stream_context;
+ (struct amdgpu_dm_connector *) stream->dm_stream_context;
if (!aconn->disallow_edp_enter_psr) {
- struct amdgpu_display_manager *dm = vblank_work->dm;
-
- amdgpu_dm_psr_enable(vblank_work->stream);
+ amdgpu_dm_psr_enable(stream);
if (dm->idle_workqueue &&
(dm->dc->config.disable_ips == DMUB_IPS_ENABLE) &&
dm->dc->idle_optimizations_allowed &&
@@ -251,33 +251,15 @@ static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
mutex_lock(&dm->dc_lock);
- if (vblank_work->enable)
+ if (vblank_work->enable) {
dm->active_vblank_irq_count++;
- else if (dm->active_vblank_irq_count)
- dm->active_vblank_irq_count--;
-
- if (dm->active_vblank_irq_count > 0)
- dc_allow_idle_optimizations(dm->dc, false);
-
- /*
- * Control PSR based on vblank requirements from OS
- *
- * If panel supports PSR SU, there's no need to disable PSR when OS is
- * submitting fast atomic commits (we infer this by whether the OS
- * requests vblank events). Fast atomic commits will simply trigger a
- * full-frame-update (FFU); a specific case of selective-update (SU)
- * where the SU region is the full hactive*vactive region. See
- * fill_dc_dirty_rects().
- */
- if (vblank_work->stream && vblank_work->stream->link && vblank_work->acrtc) {
- amdgpu_dm_crtc_set_panel_sr_feature(
- vblank_work, vblank_work->enable,
- vblank_work->acrtc->dm_irq_params.allow_sr_entry);
- }
-
- if (dm->active_vblank_irq_count == 0) {
- dc_post_update_surfaces_to_stream(dm->dc);
- dc_allow_idle_optimizations(dm->dc, true);
+ amdgpu_dm_ism_commit_event(&vblank_work->acrtc->ism,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED);
+ } else {
+ if (dm->active_vblank_irq_count > 0)
+ dm->active_vblank_irq_count--;
+ amdgpu_dm_ism_commit_event(&vblank_work->acrtc->ism,
+ DM_ISM_EVENT_ENTER_IDLE_REQUESTED);
}
mutex_unlock(&dm->dc_lock);
@@ -476,6 +458,9 @@ static struct drm_crtc_state *amdgpu_dm_crtc_duplicate_state(struct drm_crtc *cr
static void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc)
{
+ struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
+
+ amdgpu_dm_ism_fini(&acrtc->ism);
drm_crtc_cleanup(crtc);
kfree(crtc);
}
@@ -719,6 +704,35 @@ static const struct drm_crtc_helper_funcs amdgpu_dm_crtc_helper_funcs = {
.get_scanout_position = amdgpu_crtc_get_scanout_position,
};
+/*
+ * This hysteresis filter as configured will:
+ *
+ * * Search through the latest 8[filter_history_size] entries in history,
+ * skipping entries that are older than [filter_old_history_threshold] frames
+ * (0 means ignore age)
+ * * Searches for short-idle-periods that lasted shorter than
+ * 4[filter_num_frames] frames-times
+ * * If there is at least 1[filter_entry_count] short-idle-period, then a delay
+ * of 4[activation_num_delay_frames] will applied before allowing idle
+ * optimizations again.
+ * * An additional delay of 11[sso_num_frames] is applied before enabling
+ * panel-specific optimizations.
+ *
+ * The values were determined empirically on another OS, optimizing for Z8
+ * residency on APUs when running a productivity + web browsing test.
+ *
+ * TODO: Run similar tests to determine if these values are also optimal for
+ * Linux, and if each APU generation benefits differently.
+ */
+static struct amdgpu_dm_ism_config default_ism_config = {
+ .filter_num_frames = 4,
+ .filter_history_size = 8,
+ .filter_entry_count = 1,
+ .activation_num_delay_frames = 4,
+ .filter_old_history_threshold = 0,
+ .sso_num_frames = 11,
+};
+
int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
struct drm_plane *plane,
uint32_t crtc_index)
@@ -749,6 +763,8 @@ int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
if (res)
goto fail;
+ amdgpu_dm_ism_init(&acrtc->ism, &default_ism_config);
+
drm_crtc_helper_add(&acrtc->base, &amdgpu_dm_crtc_helper_funcs);
/* Create (reset) the plane 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 c1212947a77b..3a8094013a5d 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
@@ -27,6 +27,12 @@
#ifndef __AMDGPU_DM_CRTC_H__
#define __AMDGPU_DM_CRTC_H__
+void amdgpu_dm_crtc_set_panel_sr_feature(
+ struct amdgpu_display_manager *dm,
+ struct amdgpu_crtc *acrtc,
+ struct dc_stream_state *stream,
+ bool vblank_enabled, bool allow_sr_entry);
+
void amdgpu_dm_crtc_handle_vblank(struct amdgpu_crtc *acrtc);
bool amdgpu_dm_crtc_modeset_required(struct drm_crtc_state *crtc_state,
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 24bc2a86904b..2409ac72b166 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
@@ -3305,6 +3305,52 @@ static int disallow_edp_enter_psr_set(void *data, u64 val)
return 0;
}
+/* check if kernel disallow eDP enter replay state
+ * cat /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_replay
+ * 0: allow edp enter replay; 1: disallow
+ */
+static int disallow_edp_enter_replay_get(void *data, u64 *val)
+{
+ struct amdgpu_dm_connector *aconnector = data;
+
+ *val = (u64) aconnector->disallow_edp_enter_replay;
+ return 0;
+}
+
+/* set kernel disallow eDP enter replay state
+ * echo 0x0 /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_replay
+ * 0: allow edp enter replay; 1: disallow
+ *
+ * usage: test app read crc from PSR eDP rx.
+ *
+ * during kernel boot up, kernel write dpcd 0x37b to
+ * notify eDP rx replay enable.
+ * rx fw will start checking crc for rx internal logic.
+ * crc read count within dpcd 0x246 is not updated and
+ * value is 0. when eDP tx driver wants to read rx crc
+ * from dpcd 0x246, 0x270, read count 0 lead tx driver
+ * timeout.
+ *
+ * to avoid this, we add this debugfs to let test app to disbable
+ * rx replay. then test app can read non-zero crc read count.
+ *
+ * expected app sequence is as below:
+ * 1. disable eDP PHY and notify eDP rx with dpcd 0x600 = 2.
+ * 2. echo 0x1 /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_replay
+ * 3. enable eDP PHY and notify eDP rx with dpcd 0x600 = 1 but
+ * without programming dpcd 0x37b.
+ * 4. read crc from rx dpcd 0x270, 0x246, etc.
+ * 5. echo 0x0 /sys/kernel/debug/dri/0/eDP-X/disallow_edp_enter_replay.
+ * this will let eDP back to normal with replay setup dpcd 0x37b.
+ */
+static int disallow_edp_enter_replay_set(void *data, u64 val)
+{
+ struct amdgpu_dm_connector *aconnector = data;
+
+ aconnector->disallow_edp_enter_replay = val ? true : false;
+ return 0;
+}
+
static int dmub_trace_mask_set(void *data, u64 val)
{
struct amdgpu_device *adev = data;
@@ -3433,6 +3479,10 @@ DEFINE_DEBUGFS_ATTRIBUTE(disallow_edp_enter_psr_fops,
disallow_edp_enter_psr_get,
disallow_edp_enter_psr_set, "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(disallow_edp_enter_replay_fops,
+ disallow_edp_enter_replay_get,
+ disallow_edp_enter_replay_set, "%llu\n");
+
DEFINE_DEBUGFS_ATTRIBUTE(ips_residency_cntl_fops, ips_residency_cntl_get,
ips_residency_cntl_set, "%llu\n");
DEFINE_SHOW_ATTRIBUTE(current_backlight);
@@ -3635,6 +3685,8 @@ void connector_debugfs_init(struct amdgpu_dm_connector *connector)
&allow_edp_hotplug_detection_fops);
debugfs_create_file("disallow_edp_enter_psr", 0644, dir, connector,
&disallow_edp_enter_psr_fops);
+ debugfs_create_file("disallow_edp_enter_replay", 0644, dir, connector,
+ &disallow_edp_enter_replay_fops);
}
for (i = 0; i < ARRAY_SIZE(connector_debugfs_entries); i++) {
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 a09761f9882d..f3fa8eb4bcce 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
@@ -1016,6 +1016,9 @@ enum dc_edid_status dm_helpers_read_local_edid(
else
ddc = &aconnector->i2c->base;
+ if (link->dc->hwss.prepare_ddc)
+ link->dc->hwss.prepare_ddc(link);
+
/* some dongles read edid incorrectly the first time,
* do check sum and retry to make sure read correct edid.
*/
@@ -1162,9 +1165,9 @@ void dm_helpers_override_panel_settings(
link->panel_config.dsc.disable_dsc_edp = true;
if (dc_get_edp_link_panel_inst(ctx->dc, link, &panel_inst) && panel_inst == 1) {
- link->panel_config.psr.disable_psr = true;
- link->panel_config.psr.disallow_psrsu = true;;
- link->panel_config.psr.disallow_replay = true;
+ link->panel_config.psr.disable_psr = true;
+ link->panel_config.psr.disallow_psrsu = true;
+ link->panel_config.psr.disallow_replay = true;
}
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
new file mode 100644
index 000000000000..65a5cfe1e106
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.c
@@ -0,0 +1,598 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#include <linux/types.h>
+#include <drm/drm_vblank.h>
+
+#include "dc.h"
+#include "amdgpu.h"
+#include "amdgpu_dm_ism.h"
+#include "amdgpu_dm_crtc.h"
+#include "amdgpu_dm_trace.h"
+
+/**
+ * dm_ism_next_state - Get next state based on current state and event
+ *
+ * This function defines the idle state management FSM. Invalid transitions
+ * are ignored and will not progress the FSM.
+ */
+static bool dm_ism_next_state(enum amdgpu_dm_ism_state current_state,
+ enum amdgpu_dm_ism_event event,
+ enum amdgpu_dm_ism_state *next_state)
+{
+ switch (STATE_EVENT(current_state, event)) {
+ case STATE_EVENT(DM_ISM_STATE_FULL_POWER_RUNNING,
+ DM_ISM_EVENT_ENTER_IDLE_REQUESTED):
+ *next_state = DM_ISM_STATE_HYSTERESIS_WAITING;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_FULL_POWER_RUNNING,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE):
+ *next_state = DM_ISM_STATE_FULL_POWER_BUSY;
+ break;
+
+ case STATE_EVENT(DM_ISM_STATE_FULL_POWER_BUSY,
+ DM_ISM_EVENT_ENTER_IDLE_REQUESTED):
+ *next_state = DM_ISM_STATE_HYSTERESIS_BUSY;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_FULL_POWER_BUSY,
+ DM_ISM_EVENT_END_CURSOR_UPDATE):
+ *next_state = DM_ISM_STATE_FULL_POWER_RUNNING;
+ break;
+
+ case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED):
+ *next_state = DM_ISM_STATE_TIMER_ABORTED;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE):
+ *next_state = DM_ISM_STATE_HYSTERESIS_BUSY;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING,
+ DM_ISM_EVENT_TIMER_ELAPSED):
+ *next_state = DM_ISM_STATE_OPTIMIZED_IDLE;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_WAITING,
+ DM_ISM_EVENT_IMMEDIATE):
+ *next_state = DM_ISM_STATE_OPTIMIZED_IDLE;
+ break;
+
+ case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_BUSY,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED):
+ *next_state = DM_ISM_STATE_FULL_POWER_BUSY;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_HYSTERESIS_BUSY,
+ DM_ISM_EVENT_END_CURSOR_UPDATE):
+ *next_state = DM_ISM_STATE_HYSTERESIS_WAITING;
+ break;
+
+ case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED):
+ *next_state = DM_ISM_STATE_FULL_POWER_RUNNING;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE):
+ *next_state = DM_ISM_STATE_HYSTERESIS_BUSY;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE,
+ DM_ISM_EVENT_SSO_TIMER_ELAPSED):
+ case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE,
+ DM_ISM_EVENT_IMMEDIATE):
+ *next_state = DM_ISM_STATE_OPTIMIZED_IDLE_SSO;
+ break;
+
+ case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE_SSO,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED):
+ *next_state = DM_ISM_STATE_FULL_POWER_RUNNING;
+ break;
+ case STATE_EVENT(DM_ISM_STATE_OPTIMIZED_IDLE_SSO,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE):
+ *next_state = DM_ISM_STATE_HYSTERESIS_BUSY;
+ break;
+
+ case STATE_EVENT(DM_ISM_STATE_TIMER_ABORTED,
+ DM_ISM_EVENT_IMMEDIATE):
+ *next_state = DM_ISM_STATE_FULL_POWER_RUNNING;
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+}
+
+static uint64_t dm_ism_get_sso_delay(const struct amdgpu_dm_ism *ism,
+ const struct dc_stream_state *stream)
+{
+ const struct amdgpu_dm_ism_config *config = &ism->config;
+ uint32_t v_total, h_total;
+ uint64_t one_frame_ns, sso_delay_ns;
+
+ if (!stream)
+ return 0;
+
+ if (!config->sso_num_frames)
+ return 0;
+
+ v_total = stream->timing.v_total;
+ h_total = stream->timing.h_total;
+
+ one_frame_ns = div64_u64(v_total * h_total * 10000000ull,
+ stream->timing.pix_clk_100hz);
+ sso_delay_ns = config->sso_num_frames * one_frame_ns;
+
+ return sso_delay_ns;
+}
+
+/**
+ * dm_ism_get_idle_allow_delay - Calculate hysteresis-based idle allow delay
+ */
+static uint64_t dm_ism_get_idle_allow_delay(const struct amdgpu_dm_ism *ism,
+ const struct dc_stream_state *stream)
+{
+ const struct amdgpu_dm_ism_config *config = &ism->config;
+ uint32_t v_total, h_total;
+ uint64_t one_frame_ns, short_idle_ns, old_hist_ns;
+ uint32_t history_size;
+ int pos;
+ uint32_t short_idle_count = 0;
+ uint64_t ret_ns = 0;
+
+ if (!stream)
+ return 0;
+
+ if (!config->filter_num_frames)
+ return 0;
+ if (!config->filter_entry_count)
+ return 0;
+ if (!config->activation_num_delay_frames)
+ return 0;
+
+ v_total = stream->timing.v_total;
+ h_total = stream->timing.h_total;
+
+ one_frame_ns = div64_u64(v_total * h_total * 10000000ull,
+ stream->timing.pix_clk_100hz);
+
+ short_idle_ns = config->filter_num_frames * one_frame_ns;
+ old_hist_ns = config->filter_old_history_threshold * one_frame_ns;
+
+ /*
+ * Look back into the recent history and count how many times we entered
+ * idle power state for a short duration of time
+ */
+ history_size = min(
+ max(config->filter_history_size, config->filter_entry_count),
+ AMDGPU_DM_IDLE_HIST_LEN);
+ pos = ism->next_record_idx;
+
+ for (int k = 0; k < history_size; k++) {
+ if (pos <= 0 || pos > AMDGPU_DM_IDLE_HIST_LEN)
+ pos = AMDGPU_DM_IDLE_HIST_LEN;
+ pos -= 1;
+
+ if (ism->records[pos].duration_ns <= short_idle_ns)
+ short_idle_count += 1;
+
+ if (short_idle_count >= config->filter_entry_count)
+ break;
+
+ if (old_hist_ns > 0 &&
+ ism->last_idle_timestamp_ns - ism->records[pos].timestamp_ns > old_hist_ns)
+ break;
+ }
+
+ if (short_idle_count >= config->filter_entry_count)
+ ret_ns = config->activation_num_delay_frames * one_frame_ns;
+
+ return ret_ns;
+}
+
+/**
+ * dm_ism_insert_record - Insert a record into the circular history buffer
+ */
+static void dm_ism_insert_record(struct amdgpu_dm_ism *ism)
+{
+ struct amdgpu_dm_ism_record *record;
+
+ if (ism->next_record_idx < 0 ||
+ ism->next_record_idx >= AMDGPU_DM_IDLE_HIST_LEN)
+ ism->next_record_idx = 0;
+
+ record = &ism->records[ism->next_record_idx];
+ ism->next_record_idx += 1;
+
+ record->timestamp_ns = ktime_get_ns();
+ record->duration_ns =
+ record->timestamp_ns - ism->last_idle_timestamp_ns;
+}
+
+
+static void dm_ism_set_last_idle_ts(struct amdgpu_dm_ism *ism)
+{
+ ism->last_idle_timestamp_ns = ktime_get_ns();
+}
+
+
+static bool dm_ism_trigger_event(struct amdgpu_dm_ism *ism,
+ enum amdgpu_dm_ism_event event)
+{
+ enum amdgpu_dm_ism_state next_state;
+
+ bool gotNextState = dm_ism_next_state(ism->current_state, event,
+ &next_state);
+
+ if (gotNextState) {
+ ism->previous_state = ism->current_state;
+ ism->current_state = next_state;
+ }
+
+ return gotNextState;
+}
+
+
+static void dm_ism_commit_idle_optimization_state(struct amdgpu_dm_ism *ism,
+ struct dc_stream_state *stream,
+ bool vblank_enabled,
+ bool allow_panel_sso)
+{
+ struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
+ struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
+ struct amdgpu_display_manager *dm = &adev->dm;
+ int r;
+
+ trace_amdgpu_dm_ism_commit(dm->active_vblank_irq_count,
+ vblank_enabled,
+ allow_panel_sso);
+
+ /*
+ * If there is an active vblank requestor, or if SSO is being engaged,
+ * then disallow idle optimizations.
+ */
+ if (vblank_enabled || allow_panel_sso)
+ dc_allow_idle_optimizations(dm->dc, false);
+
+ /*
+ * Control PSR based on vblank requirements from OS
+ *
+ * If panel supports PSR SU/Replay, there's no need to exit self-refresh
+ * when OS is submitting fast atomic commits, as they can allow
+ * self-refresh during vblank periods.
+ */
+ if (stream && stream->link) {
+ /*
+ * If allow_panel_sso is true when disabling vblank, allow
+ * deeper panel sleep states such as PSR1 and Replay static
+ * screen optimization.
+ */
+ if (!vblank_enabled && allow_panel_sso) {
+ amdgpu_dm_crtc_set_panel_sr_feature(
+ dm, acrtc, stream, false,
+ acrtc->dm_irq_params.allow_sr_entry);
+ } else if (vblank_enabled) {
+ /* Make sure to exit SSO on vblank enable */
+ amdgpu_dm_crtc_set_panel_sr_feature(
+ dm, acrtc, stream, true,
+ acrtc->dm_irq_params.allow_sr_entry);
+ }
+ /*
+ * Else, vblank_enabled == false and allow_panel_sso == false;
+ * do nothing here.
+ */
+ }
+
+ /*
+ * Check for any active drm vblank requestors on other CRTCs
+ * (dm->active_vblank_irq_count) before allowing HW-wide idle
+ * optimizations.
+ *
+ * There's no need to have a "balanced" check when disallowing idle
+ * optimizations at the start of this func -- we should disallow
+ * whenever there's *an* active CRTC.
+ */
+ if (!vblank_enabled && dm->active_vblank_irq_count == 0) {
+ dc_post_update_surfaces_to_stream(dm->dc);
+
+ r = amdgpu_dpm_pause_power_profile(adev, true);
+ if (r)
+ dev_warn(adev->dev, "failed to set default power profile mode\n");
+
+ dc_allow_idle_optimizations(dm->dc, true);
+
+ r = amdgpu_dpm_pause_power_profile(adev, false);
+ if (r)
+ dev_warn(adev->dev, "failed to restore the power profile mode\n");
+ }
+}
+
+
+static enum amdgpu_dm_ism_event dm_ism_dispatch_power_state(
+ struct amdgpu_dm_ism *ism,
+ struct dm_crtc_state *acrtc_state,
+ enum amdgpu_dm_ism_event event)
+{
+ enum amdgpu_dm_ism_event ret = event;
+ const struct amdgpu_dm_ism_config *config = &ism->config;
+ uint64_t delay_ns, sso_delay_ns;
+
+ switch (ism->previous_state) {
+ case DM_ISM_STATE_HYSTERESIS_WAITING:
+ /*
+ * Stop the timer if it was set, and we're not running from the
+ * idle allow worker.
+ */
+ if (ism->current_state != DM_ISM_STATE_OPTIMIZED_IDLE &&
+ ism->current_state != DM_ISM_STATE_OPTIMIZED_IDLE_SSO)
+ cancel_delayed_work(&ism->delayed_work);
+ break;
+ case DM_ISM_STATE_OPTIMIZED_IDLE:
+ if (ism->current_state == DM_ISM_STATE_OPTIMIZED_IDLE_SSO)
+ break;
+ /* If idle disallow, cancel SSO work and insert record */
+ cancel_delayed_work(&ism->sso_delayed_work);
+ dm_ism_insert_record(ism);
+ dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
+ true, false);
+ break;
+ case DM_ISM_STATE_OPTIMIZED_IDLE_SSO:
+ /* Disable idle optimization */
+ dm_ism_insert_record(ism);
+ dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
+ true, false);
+ break;
+ default:
+ break;
+ }
+
+ switch (ism->current_state) {
+ case DM_ISM_STATE_HYSTERESIS_WAITING:
+ dm_ism_set_last_idle_ts(ism);
+
+ /* CRTC can be disabled; allow immediate idle */
+ if (!acrtc_state->stream) {
+ ret = DM_ISM_EVENT_IMMEDIATE;
+ break;
+ }
+
+ delay_ns = dm_ism_get_idle_allow_delay(ism,
+ acrtc_state->stream);
+ if (delay_ns == 0) {
+ ret = DM_ISM_EVENT_IMMEDIATE;
+ break;
+ }
+
+ /* Schedule worker */
+ mod_delayed_work(system_unbound_wq, &ism->delayed_work,
+ nsecs_to_jiffies(delay_ns));
+
+ break;
+ case DM_ISM_STATE_OPTIMIZED_IDLE:
+ sso_delay_ns = dm_ism_get_sso_delay(ism, acrtc_state->stream);
+ if (sso_delay_ns == 0)
+ ret = DM_ISM_EVENT_IMMEDIATE;
+ else if (config->sso_num_frames < config->filter_num_frames) {
+ /*
+ * If sso_num_frames is less than hysteresis frames, it
+ * indicates that allowing idle here, then disallowing
+ * idle after sso_num_frames has expired, will likely
+ * have a negative power impact. Skip idle allow here,
+ * and let the sso_delayed_work handle it.
+ */
+ mod_delayed_work(system_unbound_wq,
+ &ism->sso_delayed_work,
+ nsecs_to_jiffies(sso_delay_ns));
+ } else {
+ /* Enable idle optimization without SSO */
+ dm_ism_commit_idle_optimization_state(
+ ism, acrtc_state->stream, false, false);
+ mod_delayed_work(system_unbound_wq,
+ &ism->sso_delayed_work,
+ nsecs_to_jiffies(sso_delay_ns));
+ }
+ break;
+ case DM_ISM_STATE_OPTIMIZED_IDLE_SSO:
+ /* Enable static screen optimizations. */
+ dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
+ false, true);
+ break;
+ case DM_ISM_STATE_TIMER_ABORTED:
+ dm_ism_insert_record(ism);
+ dm_ism_commit_idle_optimization_state(ism, acrtc_state->stream,
+ true, false);
+ ret = DM_ISM_EVENT_IMMEDIATE;
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static char *dm_ism_events_str[DM_ISM_NUM_EVENTS] = {
+ [DM_ISM_EVENT_IMMEDIATE] = "IMMEDIATE",
+ [DM_ISM_EVENT_ENTER_IDLE_REQUESTED] = "ENTER_IDLE_REQUESTED",
+ [DM_ISM_EVENT_EXIT_IDLE_REQUESTED] = "EXIT_IDLE_REQUESTED",
+ [DM_ISM_EVENT_BEGIN_CURSOR_UPDATE] = "BEGIN_CURSOR_UPDATE",
+ [DM_ISM_EVENT_END_CURSOR_UPDATE] = "END_CURSOR_UPDATE",
+ [DM_ISM_EVENT_TIMER_ELAPSED] = "TIMER_ELAPSED",
+ [DM_ISM_EVENT_SSO_TIMER_ELAPSED] = "SSO_TIMER_ELAPSED",
+};
+
+static char *dm_ism_states_str[DM_ISM_NUM_STATES] = {
+ [DM_ISM_STATE_FULL_POWER_RUNNING] = "FULL_POWER_RUNNING",
+ [DM_ISM_STATE_FULL_POWER_BUSY] = "FULL_POWER_BUSY",
+ [DM_ISM_STATE_HYSTERESIS_WAITING] = "HYSTERESIS_WAITING",
+ [DM_ISM_STATE_HYSTERESIS_BUSY] = "HYSTERESIS_BUSY",
+ [DM_ISM_STATE_OPTIMIZED_IDLE] = "OPTIMIZED_IDLE",
+ [DM_ISM_STATE_OPTIMIZED_IDLE_SSO] = "OPTIMIZED_IDLE_SSO",
+ [DM_ISM_STATE_TIMER_ABORTED] = "TIMER_ABORTED",
+};
+
+
+void amdgpu_dm_ism_commit_event(struct amdgpu_dm_ism *ism,
+ enum amdgpu_dm_ism_event event)
+{
+ enum amdgpu_dm_ism_event next_event = event;
+ struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
+ struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
+ struct amdgpu_display_manager *dm = &adev->dm;
+ struct dm_crtc_state *acrtc_state = to_dm_crtc_state(acrtc->base.state);
+
+ /* ISM transitions must be called with mutex acquired */
+ ASSERT(mutex_is_locked(&dm->dc_lock));
+
+ if (!acrtc_state) {
+ trace_amdgpu_dm_ism_event(acrtc->crtc_id, "NO_STATE",
+ "NO_STATE", "N/A");
+ return;
+ }
+
+ do {
+ bool transition = dm_ism_trigger_event(ism, event);
+
+ next_event = DM_ISM_NUM_EVENTS;
+ if (transition) {
+ trace_amdgpu_dm_ism_event(
+ acrtc->crtc_id,
+ dm_ism_states_str[ism->previous_state],
+ dm_ism_states_str[ism->current_state],
+ dm_ism_events_str[event]);
+ next_event = dm_ism_dispatch_power_state(
+ ism, acrtc_state, next_event);
+ } else {
+ trace_amdgpu_dm_ism_event(
+ acrtc->crtc_id,
+ dm_ism_states_str[ism->current_state],
+ dm_ism_states_str[ism->current_state],
+ dm_ism_events_str[event]);
+ }
+
+ event = next_event;
+
+ } while (next_event < DM_ISM_NUM_EVENTS);
+}
+
+
+static void dm_ism_delayed_work_func(struct work_struct *work)
+{
+ struct amdgpu_dm_ism *ism =
+ container_of(work, struct amdgpu_dm_ism, delayed_work.work);
+ struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
+ struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
+ struct amdgpu_display_manager *dm = &adev->dm;
+
+ guard(mutex)(&dm->dc_lock);
+
+ amdgpu_dm_ism_commit_event(ism, DM_ISM_EVENT_TIMER_ELAPSED);
+}
+
+static void dm_ism_sso_delayed_work_func(struct work_struct *work)
+{
+ struct amdgpu_dm_ism *ism =
+ container_of(work, struct amdgpu_dm_ism, sso_delayed_work.work);
+ struct amdgpu_crtc *acrtc = ism_to_amdgpu_crtc(ism);
+ struct amdgpu_device *adev = drm_to_adev(acrtc->base.dev);
+ struct amdgpu_display_manager *dm = &adev->dm;
+
+ guard(mutex)(&dm->dc_lock);
+
+ amdgpu_dm_ism_commit_event(ism, DM_ISM_EVENT_SSO_TIMER_ELAPSED);
+}
+
+/**
+ * amdgpu_dm_ism_disable - Disable the ISM
+ *
+ * @dm: The amdgpu display manager
+ *
+ * Disable the idle state manager by disabling any ISM work, canceling pending
+ * work, and waiting for in-progress work to finish. After disabling, the system
+ * is left in DM_ISM_STATE_FULL_POWER_RUNNING state.
+ */
+void amdgpu_dm_ism_disable(struct amdgpu_display_manager *dm)
+{
+ struct drm_crtc *crtc;
+ struct amdgpu_crtc *acrtc;
+ struct amdgpu_dm_ism *ism;
+
+ drm_for_each_crtc(crtc, dm->ddev) {
+ acrtc = to_amdgpu_crtc(crtc);
+ ism = &acrtc->ism;
+
+ /* Cancel and disable any pending work */
+ disable_delayed_work_sync(&ism->delayed_work);
+ disable_delayed_work_sync(&ism->sso_delayed_work);
+
+ /*
+ * When disabled, leave in FULL_POWER_RUNNING state.
+ * EXIT_IDLE will not queue any work
+ */
+ amdgpu_dm_ism_commit_event(ism,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED);
+ }
+}
+
+/**
+ * amdgpu_dm_ism_enable - enable the ISM
+ *
+ * @dm: The amdgpu display manager
+ *
+ * Re-enable the idle state manager by enabling work that was disabled by
+ * amdgpu_dm_ism_disable.
+ */
+void amdgpu_dm_ism_enable(struct amdgpu_display_manager *dm)
+{
+ struct drm_crtc *crtc;
+ struct amdgpu_crtc *acrtc;
+ struct amdgpu_dm_ism *ism;
+
+ drm_for_each_crtc(crtc, dm->ddev) {
+ acrtc = to_amdgpu_crtc(crtc);
+ ism = &acrtc->ism;
+
+ enable_delayed_work(&ism->delayed_work);
+ enable_delayed_work(&ism->sso_delayed_work);
+ }
+}
+
+void amdgpu_dm_ism_init(struct amdgpu_dm_ism *ism,
+ struct amdgpu_dm_ism_config *config)
+{
+ ism->config = *config;
+
+ ism->current_state = DM_ISM_STATE_FULL_POWER_RUNNING;
+ ism->previous_state = DM_ISM_STATE_FULL_POWER_RUNNING;
+ ism->next_record_idx = 0;
+ ism->last_idle_timestamp_ns = 0;
+
+ INIT_DELAYED_WORK(&ism->delayed_work, dm_ism_delayed_work_func);
+ INIT_DELAYED_WORK(&ism->sso_delayed_work, dm_ism_sso_delayed_work_func);
+}
+
+
+void amdgpu_dm_ism_fini(struct amdgpu_dm_ism *ism)
+{
+ cancel_delayed_work_sync(&ism->sso_delayed_work);
+ cancel_delayed_work_sync(&ism->delayed_work);
+}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h
new file mode 100644
index 000000000000..fde0ddc8d4e4
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_ism.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __AMDGPU_DM_ISM_H__
+#define __AMDGPU_DM_ISM_H__
+
+#include <linux/workqueue.h>
+
+struct amdgpu_crtc;
+struct amdgpu_display_manager;
+
+#define AMDGPU_DM_IDLE_HIST_LEN 16
+
+enum amdgpu_dm_ism_state {
+ DM_ISM_STATE_FULL_POWER_RUNNING,
+ DM_ISM_STATE_FULL_POWER_BUSY,
+ DM_ISM_STATE_HYSTERESIS_WAITING,
+ DM_ISM_STATE_HYSTERESIS_BUSY,
+ DM_ISM_STATE_OPTIMIZED_IDLE,
+ DM_ISM_STATE_OPTIMIZED_IDLE_SSO,
+ DM_ISM_STATE_TIMER_ABORTED,
+ DM_ISM_NUM_STATES,
+};
+
+enum amdgpu_dm_ism_event {
+ DM_ISM_EVENT_IMMEDIATE,
+ DM_ISM_EVENT_ENTER_IDLE_REQUESTED,
+ DM_ISM_EVENT_EXIT_IDLE_REQUESTED,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE,
+ DM_ISM_EVENT_END_CURSOR_UPDATE,
+ DM_ISM_EVENT_TIMER_ELAPSED,
+ DM_ISM_EVENT_SSO_TIMER_ELAPSED,
+ DM_ISM_NUM_EVENTS,
+};
+
+#define STATE_EVENT(state, event) (((state) << 8) | (event))
+
+struct amdgpu_dm_ism_config {
+
+ /**
+ * @filter_num_frames: Idle periods shorter than this number of frames
+ * will be considered a "short idle period" for filtering.
+ *
+ * 0 indicates no filtering (i.e. no idle allow delay will be applied)
+ */
+ unsigned int filter_num_frames;
+
+ /**
+ * @filter_history_size: Number of recent idle periods to consider when
+ * counting the number of short idle periods.
+ */
+ unsigned int filter_history_size;
+
+ /**
+ * @filter_entry_count: When the number of short idle periods within
+ * recent &filter_history_size reaches this count, the idle allow delay
+ * will be applied.
+ *
+ * 0 indicates no filtering (i.e. no idle allow delay will be applied)
+ */
+ unsigned int filter_entry_count;
+
+ /**
+ * @activation_num_delay_frames: Defines the number of frames to wait
+ * for the idle allow delay.
+ *
+ * 0 indicates no filtering (i.e. no idle allow delay will be applied)
+ */
+ unsigned int activation_num_delay_frames;
+
+ /**
+ * @filter_old_history_threshold: A time-based restriction on top of
+ * &filter_history_size. Idle periods older than this threshold (in
+ * number of frames) will be ignored when counting the number of short
+ * idle periods.
+ *
+ * 0 indicates no time-based restriction, i.e. history is limited only
+ * by &filter_history_size.
+ */
+ unsigned int filter_old_history_threshold;
+
+ /**
+ * @sso_num_frames: Number of frames to delay before enabling static
+ * screen optimizations, such as PSR1 and Replay low HZ idle mode.
+ *
+ * 0 indicates immediate SSO enable upon allowing idle.
+ */
+ unsigned int sso_num_frames;
+};
+
+struct amdgpu_dm_ism_record {
+ /**
+ * @timestamp_ns: When idle was allowed
+ */
+ unsigned long long timestamp_ns;
+
+ /**
+ * @duration_ns: How long idle was allowed
+ */
+ unsigned long long duration_ns;
+};
+
+struct amdgpu_dm_ism {
+ struct amdgpu_dm_ism_config config;
+ unsigned long long last_idle_timestamp_ns;
+
+ enum amdgpu_dm_ism_state current_state;
+ enum amdgpu_dm_ism_state previous_state;
+
+ struct amdgpu_dm_ism_record records[AMDGPU_DM_IDLE_HIST_LEN];
+ int next_record_idx;
+
+ struct delayed_work delayed_work;
+ struct delayed_work sso_delayed_work;
+};
+
+#define ism_to_amdgpu_crtc(ism_ptr) \
+ container_of(ism_ptr, struct amdgpu_crtc, ism)
+
+void amdgpu_dm_ism_init(struct amdgpu_dm_ism *ism,
+ struct amdgpu_dm_ism_config *config);
+void amdgpu_dm_ism_fini(struct amdgpu_dm_ism *ism);
+void amdgpu_dm_ism_commit_event(struct amdgpu_dm_ism *ism,
+ enum amdgpu_dm_ism_event event);
+void amdgpu_dm_ism_disable(struct amdgpu_display_manager *dm);
+void amdgpu_dm_ism_enable(struct amdgpu_display_manager *dm);
+
+#endif
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 127207e18dcb..81e43534ec59 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
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
/*
- * Copyright 2022 Advanced Micro Devices, Inc.
+ * Copyright 2022-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -704,21 +704,21 @@ static void amdgpu_dm_plane_add_gfx12_modifiers(struct amdgpu_device *adev,
uint8_t max_comp_block[] = {2, 1, 0};
uint64_t max_comp_block_mod[ARRAY_SIZE(max_comp_block)] = {0};
uint8_t i = 0, j = 0;
- uint64_t gfx12_modifiers[] = {mod_256k, mod_64k, mod_4k, mod_256b, DRM_FORMAT_MOD_LINEAR};
+ /* Note, linear (no DCC) gets added to the modifier list for all chips by the caller. */
+ uint64_t gfx12_modifiers[] = {mod_256k, mod_64k, mod_4k, mod_256b};
for (i = 0; i < ARRAY_SIZE(max_comp_block); i++)
max_comp_block_mod[i] = AMD_FMT_MOD_SET(DCC_MAX_COMPRESSED_BLOCK, max_comp_block[i]);
/* With DCC: Best choice should be kept first. Hence, add all 256k modifiers of different
* max compressed blocks first and then move on to the next smaller sized layouts.
- * Do not add the linear modifier here, and hence the condition of size-1 for the loop
*/
- for (j = 0; j < ARRAY_SIZE(gfx12_modifiers) - 1; j++)
+ for (j = 0; j < ARRAY_SIZE(gfx12_modifiers); j++)
for (i = 0; i < ARRAY_SIZE(max_comp_block); i++)
amdgpu_dm_plane_add_modifier(mods, size, capacity,
ver | dcc | max_comp_block_mod[i] | gfx12_modifiers[j]);
- /* Without DCC. Add all modifiers including linear at the end */
+ /* Without DCC. */
for (i = 0; i < ARRAY_SIZE(gfx12_modifiers); i++)
amdgpu_dm_plane_add_modifier(mods, size, capacity, gfx12_modifiers[i]);
@@ -759,6 +759,7 @@ static int amdgpu_dm_plane_get_plane_modifiers(struct amdgpu_device *adev, unsig
case AMDGPU_FAMILY_GC_11_0_0:
case AMDGPU_FAMILY_GC_11_0_1:
case AMDGPU_FAMILY_GC_11_5_0:
+ case AMDGPU_FAMILY_GC_11_5_4:
amdgpu_dm_plane_add_gfx11_modifiers(adev, mods, &size, &capacity);
break;
case AMDGPU_FAMILY_GC_12_0_0:
@@ -953,11 +954,9 @@ static int amdgpu_dm_plane_helper_prepare_fb(struct drm_plane *plane,
return r;
}
- r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1);
- if (r) {
- drm_err(adev_to_drm(adev), "reserving fence slot failed (%d)\n", r);
+ r = dma_resv_reserve_fences(rbo->tbo.base.resv, TTM_NUM_MOVE_FENCES);
+ if (r)
goto error_unlock;
- }
if (plane->type != DRM_PLANE_TYPE_CURSOR)
domain = amdgpu_display_supported_domains(adev, rbo->flags);
@@ -1373,8 +1372,16 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
/* turn off cursor */
if (crtc_state && crtc_state->stream) {
mutex_lock(&adev->dm.dc_lock);
+ amdgpu_dm_ism_commit_event(
+ &amdgpu_crtc->ism,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE);
+
dc_stream_program_cursor_position(crtc_state->stream,
&position);
+
+ amdgpu_dm_ism_commit_event(
+ &amdgpu_crtc->ism,
+ DM_ISM_EVENT_END_CURSOR_UPDATE);
mutex_unlock(&adev->dm.dc_lock);
}
return;
@@ -1404,6 +1411,10 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
if (crtc_state->stream) {
mutex_lock(&adev->dm.dc_lock);
+ amdgpu_dm_ism_commit_event(
+ &amdgpu_crtc->ism,
+ DM_ISM_EVENT_BEGIN_CURSOR_UPDATE);
+
if (!dc_stream_program_cursor_attributes(crtc_state->stream,
&attributes))
DRM_ERROR("DC failed to set cursor attributes\n");
@@ -1411,6 +1422,10 @@ void amdgpu_dm_plane_handle_cursor_update(struct drm_plane *plane,
if (!dc_stream_program_cursor_position(crtc_state->stream,
&position))
DRM_ERROR("DC failed to set cursor position\n");
+
+ amdgpu_dm_ism_commit_event(
+ &amdgpu_crtc->ism,
+ DM_ISM_EVENT_END_CURSOR_UPDATE);
mutex_unlock(&adev->dm.dc_lock);
}
}
@@ -1907,7 +1922,8 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
drm_plane_create_zpos_immutable_property(plane, 255);
}
- if (plane->type == DRM_PLANE_TYPE_PRIMARY &&
+ if ((plane->type == DRM_PLANE_TYPE_PRIMARY ||
+ plane->type == DRM_PLANE_TYPE_OVERLAY) &&
plane_cap &&
(plane_cap->pixel_format_support.nv12 ||
plane_cap->pixel_format_support.p010)) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index aa56fd6d56c3..e0fab8878d19 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -753,6 +753,69 @@ TRACE_EVENT(amdgpu_dm_brightness,
)
);
+TRACE_EVENT(amdgpu_dm_ism_commit,
+ TP_PROTO(
+ int active_vblank_irq_count,
+ bool vblank_enabled,
+ bool allow_panel_sso
+ ),
+ TP_ARGS(
+ active_vblank_irq_count,
+ vblank_enabled,
+ allow_panel_sso
+ ),
+ TP_STRUCT__entry(
+ __field(int, active_vblank_irq_count)
+ __field(bool, vblank_enabled)
+ __field(bool, allow_panel_sso)
+ ),
+ TP_fast_assign(
+ __entry->active_vblank_irq_count = active_vblank_irq_count;
+ __entry->vblank_enabled = vblank_enabled;
+ __entry->allow_panel_sso = allow_panel_sso;
+ ),
+ TP_printk(
+ "active_vblank_irq_count=%d vblank_enabled=%d allow_panel_sso=%d",
+ __entry->active_vblank_irq_count,
+ __entry->vblank_enabled,
+ __entry->allow_panel_sso
+ )
+);
+
+TRACE_EVENT(amdgpu_dm_ism_event,
+ TP_PROTO(
+ int crtc_id,
+ const char *prev_state,
+ const char *curr_state,
+ const char *event
+ ),
+ TP_ARGS(
+ crtc_id,
+ prev_state,
+ curr_state,
+ event
+ ),
+ TP_STRUCT__entry(
+ __field(int, crtc_id)
+ __string(prev_state, prev_state)
+ __string(curr_state, curr_state)
+ __string(event, event)
+ ),
+ TP_fast_assign(
+ __entry->crtc_id = crtc_id;
+ __assign_str(prev_state);
+ __assign_str(curr_state);
+ __assign_str(event);
+ ),
+ TP_printk(
+ "[CRTC %d] %s -> %s on event %s",
+ __entry->crtc_id,
+ __get_str(prev_state),
+ __get_str(curr_state),
+ __get_str(event))
+);
+
+
#endif /* _AMDGPU_DM_TRACE_H_ */
#undef TRACE_INCLUDE_PATH
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
index d9527c05fc87..110f0173eee6 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
@@ -106,11 +106,9 @@ static int amdgpu_dm_wb_prepare_job(struct drm_writeback_connector *wb_connector
return r;
}
- r = dma_resv_reserve_fences(rbo->tbo.base.resv, 1);
- if (r) {
- drm_err(adev_to_drm(adev), "reserving fence slot failed (%d)\n", r);
+ r = dma_resv_reserve_fences(rbo->tbo.base.resv, TTM_NUM_MOVE_FENCES);
+ if (r)
goto error_unlock;
- }
domain = amdgpu_display_supported_domains(adev, rbo->flags);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
index e46f8ce41d87..8ba9b4f56f87 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
@@ -53,12 +53,31 @@ inline void dc_assert_fp_enabled(void)
{
int depth;
- depth = __this_cpu_read(fpu_recursion_depth);
+ depth = this_cpu_read(fpu_recursion_depth);
ASSERT(depth >= 1);
}
/**
+ * dc_assert_fp_enabled - Check if FPU protection is enabled
+ *
+ * This function tells if the code is already under FPU protection or not. A
+ * function that works as an API for a set of FPU operations can use this
+ * function for checking if the caller invoked it after DC_FP_START(). For
+ * example, take a look at dcn20_fpu.c file.
+ *
+ * Similar to dc_assert_fp_enabled, but does not assert, returns status instead.
+ */
+inline bool dc_is_fp_enabled(void)
+{
+ int depth;
+
+ depth = this_cpu_read(fpu_recursion_depth);
+
+ return (depth >= 1);
+}
+
+/**
* dc_fpu_begin - Enables FPU protection
* @function_name: A string containing the function name for debug purposes
* (usually __func__)
@@ -77,7 +96,7 @@ void dc_fpu_begin(const char *function_name, const int line)
WARN_ON_ONCE(!in_task());
preempt_disable();
- depth = __this_cpu_inc_return(fpu_recursion_depth);
+ depth = this_cpu_inc_return(fpu_recursion_depth);
if (depth == 1) {
BUG_ON(!kernel_fpu_available());
kernel_fpu_begin();
@@ -100,7 +119,7 @@ void dc_fpu_end(const char *function_name, const int line)
{
int depth;
- depth = __this_cpu_dec_return(fpu_recursion_depth);
+ depth = this_cpu_dec_return(fpu_recursion_depth);
if (depth == 0) {
kernel_fpu_end();
} else {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
index 4e921632bc4e..5e95419d3798 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.h
@@ -28,15 +28,30 @@
#define __DC_FPU_H__
void dc_assert_fp_enabled(void);
+bool dc_is_fp_enabled(void);
void dc_fpu_begin(const char *function_name, const int line);
void dc_fpu_end(const char *function_name, const int line);
#ifndef _LINUX_FPU_COMPILATION_UNIT
#define DC_FP_START() dc_fpu_begin(__func__, __LINE__)
#define DC_FP_END() dc_fpu_end(__func__, __LINE__)
+#ifdef CONFIG_DRM_AMD_DC_FP
+#define DC_RUN_WITH_PREEMPTION_ENABLED(code) \
+ do { \
+ bool dc_fp_enabled = dc_is_fp_enabled(); \
+ if (dc_fp_enabled) \
+ DC_FP_END(); \
+ code; \
+ if (dc_fp_enabled) \
+ DC_FP_START(); \
+ } while (0)
+#else
+#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
+#endif // !CONFIG_DRM_AMD_DC_FP
#else
#define DC_FP_START() BUILD_BUG()
#define DC_FP_END() BUILD_BUG()
-#endif
+#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
+#endif // !_LINUX_FPU_COMPILATION_UNIT
#endif /* __DC_FPU_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c
index 8c54c02a0e26..f37a43f4172e 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/dce_calcs.c
@@ -2010,10 +2010,10 @@ static void calculate_bandwidth(
}
/*output link bit per pixel supported*/
for (k = 0; k <= maximum_number_of_surfaces - 1; k++) {
- data->output_bpphdmi[k] = bw_def_na;
- data->output_bppdp4_lane_hbr[k] = bw_def_na;
- data->output_bppdp4_lane_hbr2[k] = bw_def_na;
- data->output_bppdp4_lane_hbr3[k] = bw_def_na;
+ data->output_bpphdmi[k] = (uint32_t)bw_def_na;
+ data->output_bppdp4_lane_hbr[k] = (uint32_t)bw_def_na;
+ data->output_bppdp4_lane_hbr2[k] = (uint32_t)bw_def_na;
+ data->output_bppdp4_lane_hbr3[k] = (uint32_t)bw_def_na;
if (data->enable[k]) {
data->output_bpphdmi[k] = bw_fixed_to_int(bw_mul(bw_div(bw_min2(bw_int_to_fixed(600), data->max_phyclk), data->pixel_rate[k]), bw_int_to_fixed(24)));
if (bw_meq(data->max_phyclk, bw_int_to_fixed(270))) {
diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
index 6073cadde76c..fa10f85df3db 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
@@ -503,6 +503,7 @@ struct fixed31_32 dc_fixpt_from_int_dy(unsigned int int_value,
unsigned int integer_bits,
unsigned int fractional_bits)
{
+ (void)integer_bits;
struct fixed31_32 fixpt_value = dc_fixpt_from_int(int_value);
fixpt_value.value |= (long long)frac_value << (FIXED31_32_BITS_PER_FRACTIONAL_PART - fractional_bits);
diff --git a/drivers/gpu/drm/amd/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c
index a8b750ff8573..e8736c134b8d 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/vector.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c
@@ -56,6 +56,7 @@ static bool dal_vector_presized_costruct(struct vector *vector,
void *initial_value,
uint32_t struct_size)
{
+ (void)ctx;
uint32_t i;
vector->container = NULL;
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
index 73e3c45eeeba..dd362071a6c9 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
@@ -780,28 +780,31 @@ static enum bp_result bios_parser_encoder_control(
return bp->cmd_tbl.dig_encoder_control(bp, cntl);
}
+static enum bp_result bios_parser_external_encoder_control(
+ struct dc_bios *dcb,
+ struct bp_external_encoder_control *cntl)
+{
+ struct bios_parser *bp = BP_FROM_DCB(dcb);
+
+ if (!bp->cmd_tbl.external_encoder_control)
+ return BP_RESULT_UNSUPPORTED;
+
+ return bp->cmd_tbl.external_encoder_control(bp, cntl);
+}
+
static enum bp_result bios_parser_dac_load_detection(
struct dc_bios *dcb,
- enum engine_id engine_id,
- enum dal_device_type device_type,
- uint32_t enum_id)
+ enum engine_id engine_id)
{
struct bios_parser *bp = BP_FROM_DCB(dcb);
struct dc_context *ctx = dcb->ctx;
struct bp_load_detection_parameters bp_params = {0};
- enum bp_result bp_result;
+ enum bp_result bp_result = BP_RESULT_UNSUPPORTED;
uint32_t bios_0_scratch;
uint32_t device_id_mask = 0;
- bp_params.engine_id = engine_id;
- bp_params.device_id = get_support_mask_for_device_id(device_type, enum_id);
-
- if (engine_id != ENGINE_ID_DACA &&
- engine_id != ENGINE_ID_DACB)
- return BP_RESULT_UNSUPPORTED;
-
- if (!bp->cmd_tbl.dac_load_detection)
- return BP_RESULT_UNSUPPORTED;
+ bp_params.device_id = get_support_mask_for_device_id(
+ DEVICE_TYPE_CRT, engine_id == ENGINE_ID_DACB ? 2 : 1);
if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT)
device_id_mask = ATOM_S0_CRT1_MASK;
@@ -815,7 +818,13 @@ static enum bp_result bios_parser_dac_load_detection(
bios_0_scratch &= ~device_id_mask;
dm_write_reg(ctx, bp->base.regs->BIOS_SCRATCH_0, bios_0_scratch);
- bp_result = bp->cmd_tbl.dac_load_detection(bp, &bp_params);
+ if (engine_id == ENGINE_ID_DACA || engine_id == ENGINE_ID_DACB) {
+ if (!bp->cmd_tbl.dac_load_detection)
+ return BP_RESULT_UNSUPPORTED;
+
+ bp_params.engine_id = engine_id;
+ bp_result = bp->cmd_tbl.dac_load_detection(bp, &bp_params);
+ }
if (bp_result != BP_RESULT_OK)
return bp_result;
@@ -1954,7 +1963,7 @@ static enum bp_result get_gpio_i2c_info(struct bios_parser *bp,
count = (le16_to_cpu(header->sHeader.usStructureSize)
- sizeof(ATOM_COMMON_TABLE_HEADER))
/ sizeof(ATOM_GPIO_I2C_ASSIGMENT);
- if (count < record->sucI2cId.bfI2C_LineMux)
+ if (count <= record->sucI2cId.bfI2C_LineMux)
return BP_RESULT_BADBIOSTABLE;
/* get the GPIO_I2C_INFO */
@@ -2687,6 +2696,7 @@ static enum bp_result update_slot_layout_info(struct dc_bios *dcb,
struct slot_layout_info *slot_layout_info,
unsigned int record_offset)
{
+ (void)i;
unsigned int j;
struct bios_parser *bp;
ATOM_BRACKET_LAYOUT_RECORD *record;
@@ -2912,6 +2922,8 @@ static const struct dc_vbios_funcs vbios_funcs = {
.encoder_control = bios_parser_encoder_control,
+ .external_encoder_control = bios_parser_external_encoder_control,
+
.dac_load_detection = bios_parser_dac_load_detection,
.transmitter_control = bios_parser_transmitter_control,
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
index 94fddf22f5a9..a1c08e1cc411 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
@@ -205,6 +205,7 @@ static enum bp_result bios_parser_get_src_obj(struct dc_bios *dcb,
struct graphics_object_id object_id, uint32_t index,
struct graphics_object_id *src_object_id)
{
+ (void)index;
struct bios_parser *bp = BP_FROM_DCB(dcb);
unsigned int i;
enum bp_result bp_result = BP_RESULT_BADINPUT;
@@ -765,6 +766,7 @@ static enum bp_result bios_parser_get_device_tag(
uint32_t device_tag_index,
struct connector_device_tag_info *info)
{
+ (void)device_tag_index;
struct bios_parser *bp = BP_FROM_DCB(dcb);
struct atom_display_object_path_v2 *object;
@@ -809,6 +811,7 @@ static enum bp_result get_ss_info_v4_1(
uint32_t index,
struct spread_spectrum_info *ss_info)
{
+ (void)index;
enum bp_result result = BP_RESULT_OK;
struct atom_display_controller_info_v4_1 *disp_cntl_tbl = NULL;
struct atom_smu_info_v3_3 *smu_info = NULL;
@@ -897,6 +900,7 @@ static enum bp_result get_ss_info_v4_2(
uint32_t index,
struct spread_spectrum_info *ss_info)
{
+ (void)index;
enum bp_result result = BP_RESULT_OK;
struct atom_display_controller_info_v4_2 *disp_cntl_tbl = NULL;
struct atom_smu_info_v3_1 *smu_info = NULL;
@@ -977,6 +981,7 @@ static enum bp_result get_ss_info_v4_5(
uint32_t index,
struct spread_spectrum_info *ss_info)
{
+ (void)index;
enum bp_result result = BP_RESULT_OK;
struct atom_display_controller_info_v4_5 *disp_cntl_tbl = NULL;
@@ -1604,6 +1609,8 @@ static uint32_t bios_parser_get_ss_entry_number(
struct dc_bios *dcb,
enum as_signal_type signal)
{
+ (void)dcb;
+ (void)signal;
/* TODO: DAL2 atomfirmware implementation does not need this.
* why DAL3 need this?
*/
@@ -3536,6 +3543,8 @@ static uint16_t bios_parser_pack_data_tables(
struct dc_bios *dcb,
void *dst)
{
+ (void)dcb;
+ (void)dst;
// TODO: There is data bytes alignment issue, disable it for now.
return 0;
}
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c
index b692fa37402d..f6e22dcecf29 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c
@@ -226,6 +226,28 @@ static enum bp_result encoder_control_dig2_v1(
return result;
}
+static uint8_t dc_color_depth_to_atom(enum dc_color_depth color_depth)
+{
+ switch (color_depth) {
+ case COLOR_DEPTH_UNDEFINED:
+ return PANEL_BPC_UNDEFINE;
+ case COLOR_DEPTH_666:
+ return PANEL_6BIT_PER_COLOR;
+ default:
+ case COLOR_DEPTH_888:
+ return PANEL_8BIT_PER_COLOR;
+ case COLOR_DEPTH_101010:
+ return PANEL_10BIT_PER_COLOR;
+ case COLOR_DEPTH_121212:
+ return PANEL_12BIT_PER_COLOR;
+ case COLOR_DEPTH_141414:
+ dm_error("14-bit color not supported by ATOMBIOS\n");
+ return PANEL_BPC_UNDEFINE;
+ case COLOR_DEPTH_161616:
+ return PANEL_16BIT_PER_COLOR;
+ }
+}
+
static enum bp_result encoder_control_digx_v3(
struct bios_parser *bp,
struct bp_encoder_control *cntl)
@@ -248,23 +270,7 @@ static enum bp_result encoder_control_digx_v3(
cntl->signal,
cntl->enable_dp_audio);
params.ucLaneNum = (uint8_t)(cntl->lanes_number);
-
- switch (cntl->color_depth) {
- case COLOR_DEPTH_888:
- params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
- break;
- case COLOR_DEPTH_101010:
- params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
- break;
- case COLOR_DEPTH_121212:
- params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
- break;
- case COLOR_DEPTH_161616:
- params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
- break;
- default:
- break;
- }
+ params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth);
if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
result = BP_RESULT_OK;
@@ -294,23 +300,7 @@ static enum bp_result encoder_control_digx_v4(
cntl->signal,
cntl->enable_dp_audio));
params.ucLaneNum = (uint8_t)(cntl->lanes_number);
-
- switch (cntl->color_depth) {
- case COLOR_DEPTH_888:
- params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
- break;
- case COLOR_DEPTH_101010:
- params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
- break;
- case COLOR_DEPTH_121212:
- params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
- break;
- case COLOR_DEPTH_161616:
- params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
- break;
- default:
- break;
- }
+ params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth);
if (EXEC_BIOS_CMD_TABLE(DIGxEncoderControl, params))
result = BP_RESULT_OK;
@@ -334,23 +324,7 @@ static enum bp_result encoder_control_digx_v5(
cntl->signal,
cntl->enable_dp_audio));
params.ucLaneNum = (uint8_t)(cntl->lanes_number);
-
- switch (cntl->color_depth) {
- case COLOR_DEPTH_888:
- params.ucBitPerColor = PANEL_8BIT_PER_COLOR;
- break;
- case COLOR_DEPTH_101010:
- params.ucBitPerColor = PANEL_10BIT_PER_COLOR;
- break;
- case COLOR_DEPTH_121212:
- params.ucBitPerColor = PANEL_12BIT_PER_COLOR;
- break;
- case COLOR_DEPTH_161616:
- params.ucBitPerColor = PANEL_16BIT_PER_COLOR;
- break;
- default:
- break;
- }
+ params.ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth);
if (cntl->signal == SIGNAL_TYPE_HDMI_TYPE_A)
switch (cntl->color_depth) {
@@ -1797,30 +1771,7 @@ static enum bp_result select_crtc_source_v3(
&params.ucEncodeMode))
return BP_RESULT_BADINPUT;
- switch (bp_params->color_depth) {
- case COLOR_DEPTH_UNDEFINED:
- params.ucDstBpc = PANEL_BPC_UNDEFINE;
- break;
- case COLOR_DEPTH_666:
- params.ucDstBpc = PANEL_6BIT_PER_COLOR;
- break;
- default:
- case COLOR_DEPTH_888:
- params.ucDstBpc = PANEL_8BIT_PER_COLOR;
- break;
- case COLOR_DEPTH_101010:
- params.ucDstBpc = PANEL_10BIT_PER_COLOR;
- break;
- case COLOR_DEPTH_121212:
- params.ucDstBpc = PANEL_12BIT_PER_COLOR;
- break;
- case COLOR_DEPTH_141414:
- dm_error("14-bit color not supported by SelectCRTC_Source v3\n");
- break;
- case COLOR_DEPTH_161616:
- params.ucDstBpc = PANEL_16BIT_PER_COLOR;
- break;
- }
+ params.ucDstBpc = dc_color_depth_to_atom(bp_params->color_depth);
if (EXEC_BIOS_CMD_TABLE(SelectCRTC_Source, params))
result = BP_RESULT_OK;
@@ -2569,6 +2520,7 @@ static enum bp_result external_encoder_control_v3(
cpu_to_le16((uint16_t)cntl->connector_obj_id.id);
break;
case EXTERNAL_ENCODER_CONTROL_SETUP:
+ case EXTERNAL_ENCODER_CONTROL_ENABLE:
/* EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 pixel clock unit in
* 10KHz
* output display device pixel clock frequency in unit of 10KHz.
@@ -2585,26 +2537,24 @@ static enum bp_result external_encoder_control_v3(
if (is_input_signal_dp) {
/* Bit[0]: indicate link rate, =1: 2.7Ghz, =0: 1.62Ghz,
* only valid in encoder setup with DP mode. */
- if (LINK_RATE_HIGH == cntl->link_rate)
- cntl_params->ucConfig |= 1;
+ if (cntl->link_rate == LINK_RATE_LOW)
+ cntl_params->ucConfig |=
+ EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_1_62GHZ;
+ else if (cntl->link_rate == LINK_RATE_HIGH)
+ cntl_params->ucConfig |=
+ EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ;
+ else
+ dm_error("Link rate not supported by external encoder");
+
/* output color depth Indicate encoder data bpc format
* in DP mode, only valid in encoder setup in DP mode.
*/
- cntl_params->ucBitPerColor =
- (uint8_t)(cntl->color_depth);
+ cntl_params->ucBitPerColor = dc_color_depth_to_atom(cntl->color_depth);
}
/* Indicate how many lanes used by external encoder, only valid
* in encoder setup and enableoutput. */
cntl_params->ucLaneNum = (uint8_t)(cntl->lanes_number);
break;
- case EXTERNAL_ENCODER_CONTROL_ENABLE:
- cntl_params->usPixelClock =
- cpu_to_le16((uint16_t)(cntl->pixel_clock / 10));
- cntl_params->ucEncoderMode =
- (uint8_t)bp->cmd_helper->encoder_mode_bp_to_atom(
- cntl->signal, false);
- cntl_params->ucLaneNum = (uint8_t)cntl->lanes_number;
- break;
default:
break;
}
diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
index f2b1720a6a66..17ef515c6c69 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
@@ -783,6 +783,8 @@ static enum bp_result external_encoder_control_v3(
struct bios_parser *bp,
struct bp_external_encoder_control *cntl)
{
+ (void)bp;
+ (void)cntl;
/* TODO */
return BP_RESULT_OK;
}
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 268e2414b34f..a93a8860535a 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
@@ -84,6 +84,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2(
case DCN_VERSION_3_51:
case DCN_VERSION_3_6:
case DCN_VERSION_4_01:
+ case DCN_VERSION_4_2:
*h = dal_cmd_tbl_helper_dce112_get_table2();
return true;
diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c
index 3099128223df..cec61c9d7263 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/dce110/command_table_helper_dce110.c
@@ -94,6 +94,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
{
+ (void)id;
/* On any ASIC after DCE80, we manually program the DIG_FE
* selection (see connect_dig_be_to_fe function of the link
* encoder), so translation should always return 0 (no FE).
diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c
index 349f0e5d5856..478465fba224 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper2_dce112.c
@@ -93,6 +93,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
{
+ (void)id;
/* On any ASIC after DCE80, we manually program the DIG_FE
* selection (see connect_dig_be_to_fe function of the link
* encoder), so translation should always return 0 (no FE).
diff --git a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c
index 1a5fefcde8af..6b8a87f2c49e 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/dce112/command_table_helper_dce112.c
@@ -91,6 +91,7 @@ static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
{
+ (void)id;
/* On any ASIC after DCE80, we manually program the DIG_FE
* selection (see connect_dig_be_to_fe function of the link
* encoder), so translation should always return 0 (no FE).
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
index 60021671b386..98911ef56c2e 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright 2017 Advanced Micro Devices, Inc.
+# Copyright 2017-2026 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -29,18 +29,6 @@ AMD_DAL_CLK_MGR = $(addprefix $(AMDDALPATH)/dc/clk_mgr/,$(CLK_MGR))
AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR)
-
-ifdef CONFIG_DRM_AMD_DC_SI
-###############################################################################
-# DCE 60
-###############################################################################
-CLK_MGR_DCE60 = dce60_clk_mgr.o
-
-AMD_DAL_CLK_MGR_DCE60 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dce60/,$(CLK_MGR_DCE60))
-
-AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCE60)
-endif
-
###############################################################################
# DCE 100 and DCE8x
###############################################################################
@@ -188,4 +176,13 @@ CLK_MGR_DCN401 = dcn401_clk_mgr.o dcn401_clk_mgr_smu_msg.o
AMD_DAL_CLK_MGR_DCN401 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn401/,$(CLK_MGR_DCN401))
AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN401)
+
+###############################################################################
+# DCN42
+###############################################################################
+CLK_MGR_DCN42 = dcn42_smu.o dcn42_clk_mgr.o
+
+AMD_DAL_CLK_MGR_DCN42 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn42/,$(CLK_MGR_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN42)
endif
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 d237d7b41dfd..880bce368238 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
@@ -34,7 +34,6 @@
#include "dce110/dce110_clk_mgr.h"
#include "dce112/dce112_clk_mgr.h"
#include "dce120/dce120_clk_mgr.h"
-#include "dce60/dce60_clk_mgr.h"
#include "dcn10/rv1_clk_mgr.h"
#include "dcn10/rv2_clk_mgr.h"
#include "dcn20/dcn20_clk_mgr.h"
@@ -49,6 +48,7 @@
#include "dcn32/dcn32_clk_mgr.h"
#include "dcn35/dcn35_clk_mgr.h"
#include "dcn401/dcn401_clk_mgr.h"
+#include "dcn42/dcn42_clk_mgr.h"
int clk_mgr_helper_get_active_display_cnt(
struct dc *dc,
@@ -78,6 +78,7 @@ int clk_mgr_helper_get_active_plane_cnt(
struct dc *dc,
struct dc_state *context)
{
+ (void)dc;
int i, total_plane_count;
total_plane_count = 0;
@@ -97,7 +98,7 @@ void clk_mgr_exit_optimized_pwr_state(const struct dc *dc, struct clk_mgr *clk_m
{
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link = NULL;
- int edp_num;
+ unsigned int edp_num;
unsigned int panel_inst;
dc_get_edp_links(dc, edp_links, &edp_num);
@@ -123,7 +124,7 @@ void clk_mgr_optimize_pwr_state(const struct dc *dc, struct clk_mgr *clk_mgr)
{
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link = NULL;
- int edp_num;
+ unsigned int edp_num;
unsigned int panel_inst;
dc_get_edp_links(dc, edp_links, &edp_num);
@@ -149,18 +150,7 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
struct hw_asic_id asic_id = ctx->asic_id;
switch (asic_id.chip_family) {
-#if defined(CONFIG_DRM_AMD_DC_SI)
- case FAMILY_SI: {
- struct clk_mgr_internal *clk_mgr = kzalloc_obj(*clk_mgr);
-
- if (clk_mgr == NULL) {
- BREAK_TO_DEBUGGER();
- return NULL;
- }
- dce60_clk_mgr_construct(ctx, clk_mgr);
- return &clk_mgr->base;
- }
-#endif
+ case FAMILY_SI:
case FAMILY_CI:
case FAMILY_KV: {
struct clk_mgr_internal *clk_mgr = kzalloc_obj(*clk_mgr);
@@ -374,6 +364,18 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p
return &clk_mgr->base;
}
break;
+ case AMDGPU_FAMILY_GC_11_5_4: {
+ struct clk_mgr_dcn42 *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL);
+
+ if (clk_mgr == NULL) {
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+
+ dcn42_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg);
+ return &clk_mgr->base.base;
+ }
+ break;
#endif /* CONFIG_DRM_AMD_DC_FP */
default:
ASSERT(0); /* Unknown Asic */
@@ -431,6 +433,9 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base)
case AMDGPU_FAMILY_GC_12_0_0:
dcn401_clk_mgr_destroy(clk_mgr);
break;
+ case AMDGPU_FAMILY_GC_11_5_4:
+ dcn42_clk_mgr_destroy(clk_mgr);
+ break;
default:
break;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
index 6131ede2db7a..6d41df52d7c9 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce100/dce_clk_mgr.c
@@ -62,6 +62,18 @@ static const struct clk_mgr_mask disp_clk_mask = {
CLK_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(_MASK)
};
+/* Max clock values for each state indexed by "enum clocks_state": */
+static const struct state_dependent_clocks dce60_max_clks_by_state[] = {
+/* ClocksStateInvalid - should not be used */
+{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
+/* ClocksStateUltraLow - not expected to be used for DCE 6.0 */
+{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
+/* ClocksStateLow */
+{ .display_clk_khz = 352000, .pixel_clk_khz = 330000},
+/* ClocksStateNominal */
+{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 },
+/* ClocksStatePerformance */
+{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } };
/* Max clock values for each state indexed by "enum clocks_state": */
static const struct state_dependent_clocks dce80_max_clks_by_state[] = {
@@ -126,6 +138,20 @@ int dce_adjust_dp_ref_freq_for_ss(struct clk_mgr_internal *clk_mgr_dce, int dp_r
return dp_ref_clk_khz;
}
+static int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ struct dc_context *ctx = clk_mgr_base->ctx;
+ int dp_ref_clk_khz = 0;
+
+ if (ASIC_REV_IS_TAHITI_P(ctx->asic_id.hw_internal_rev))
+ dp_ref_clk_khz = ctx->dc_bios->fw_info.default_display_engine_pll_frequency;
+ else
+ dp_ref_clk_khz = clk_mgr_base->clks.dispclk_khz;
+
+ return dce_adjust_dp_ref_freq_for_ss(clk_mgr, dp_ref_clk_khz);
+}
+
int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base)
{
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
@@ -134,6 +160,9 @@ int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base)
int dp_ref_clk_khz;
int target_div;
+ if (clk_mgr_base->ctx->dce_version <= DCE_VERSION_6_4)
+ return dce60_get_dp_ref_freq_khz(clk_mgr_base);
+
/* ASSERT DP Reference Clock source is from DFS*/
REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel);
ASSERT(dprefclk_src_sel == 0);
@@ -441,27 +470,37 @@ void dce_clk_mgr_construct(
struct clk_mgr *base = &clk_mgr->base;
struct dm_pp_static_clock_info static_clk_info = {0};
- memcpy(clk_mgr->max_clks_by_state,
- dce80_max_clks_by_state,
- sizeof(dce80_max_clks_by_state));
+ if (ctx->dce_version <= DCE_VERSION_6_4)
+ memcpy(clk_mgr->max_clks_by_state,
+ dce60_max_clks_by_state,
+ sizeof(dce60_max_clks_by_state));
+ else
+ memcpy(clk_mgr->max_clks_by_state,
+ dce80_max_clks_by_state,
+ sizeof(dce80_max_clks_by_state));
+
base->ctx = ctx;
base->funcs = &dce_funcs;
- clk_mgr->regs = &disp_clk_regs;
- clk_mgr->clk_mgr_shift = &disp_clk_shift;
- clk_mgr->clk_mgr_mask = &disp_clk_mask;
- clk_mgr->dfs_bypass_disp_clk = 0;
+ if (ctx->dce_version >= DCE_VERSION_8_0) {
+ clk_mgr->regs = &disp_clk_regs;
+ clk_mgr->clk_mgr_shift = &disp_clk_shift;
+ clk_mgr->clk_mgr_mask = &disp_clk_mask;
+ }
+ clk_mgr->dfs_bypass_disp_clk = 0;
clk_mgr->dprefclk_ss_percentage = 0;
clk_mgr->dprefclk_ss_divider = 1000;
clk_mgr->ss_on_dprefclk = false;
- if (dm_pp_get_static_clocks(ctx, &static_clk_info))
- clk_mgr->max_clks_state = static_clk_info.max_clocks_state;
- else
- clk_mgr->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL;
- clk_mgr->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID;
+ if (ctx->dce_version >= DCE_VERSION_8_0) {
+ if (dm_pp_get_static_clocks(ctx, &static_clk_info))
+ clk_mgr->max_clks_state = static_clk_info.max_clocks_state;
+ else
+ clk_mgr->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL;
+ clk_mgr->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID;
+ }
base->clks.max_supported_dispclk_khz =
clk_mgr->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz;
@@ -469,4 +508,3 @@ void dce_clk_mgr_construct(
dce_clock_read_integrated_info(clk_mgr);
dce_clock_read_ss_info(clk_mgr);
}
-
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
index d50b9440210e..cd4c45516616 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce110/dce110_clk_mgr.c
@@ -92,7 +92,7 @@ static int determine_sclk_from_bounding_box(
uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context)
{
uint8_t j;
- uint32_t min_vertical_blank_time = -1;
+ uint32_t min_vertical_blank_time = (uint32_t)-1;
for (j = 0; j < context->stream_count; j++) {
struct dc_stream_state *stream = context->streams[j];
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c
deleted file mode 100644
index 69dd80d9f738..000000000000
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-
-#include "dccg.h"
-#include "clk_mgr_internal.h"
-#include "dce100/dce_clk_mgr.h"
-#include "dce110/dce110_clk_mgr.h"
-#include "dce60_clk_mgr.h"
-#include "reg_helper.h"
-#include "dmcu.h"
-#include "core_types.h"
-#include "dal_asic_id.h"
-
-/*
- * Currently the register shifts and masks in this file are used for dce60
- * which has no DPREFCLK_CNTL register
- * TODO: remove this when DENTIST_DISPCLK_CNTL
- * is moved to dccg, where it belongs
- */
-#include "dce/dce_6_0_d.h"
-#include "dce/dce_6_0_sh_mask.h"
-
-#define REG(reg) \
- (clk_mgr->regs->reg)
-
-#undef FN
-#define FN(reg_name, field_name) \
- clk_mgr->clk_mgr_shift->field_name, clk_mgr->clk_mgr_mask->field_name
-
-/* set register offset */
-#define SR(reg_name)\
- .reg_name = mm ## reg_name
-
-static const struct clk_mgr_registers disp_clk_regs = {
- CLK_COMMON_REG_LIST_DCE60_BASE()
-};
-
-static const struct clk_mgr_shift disp_clk_shift = {
- CLK_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(__SHIFT)
-};
-
-static const struct clk_mgr_mask disp_clk_mask = {
- CLK_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(_MASK)
-};
-
-
-/* Max clock values for each state indexed by "enum clocks_state": */
-static const struct state_dependent_clocks dce60_max_clks_by_state[] = {
-/* ClocksStateInvalid - should not be used */
-{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
-/* ClocksStateUltraLow - not expected to be used for DCE 6.0 */
-{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
-/* ClocksStateLow */
-{ .display_clk_khz = 352000, .pixel_clk_khz = 330000},
-/* ClocksStateNominal */
-{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 },
-/* ClocksStatePerformance */
-{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } };
-
-static int dce60_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr_base)
-{
- struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
- struct dc_context *ctx = clk_mgr_base->ctx;
- int dp_ref_clk_khz = 0;
-
- if (ASIC_REV_IS_TAHITI_P(ctx->asic_id.hw_internal_rev))
- dp_ref_clk_khz = ctx->dc_bios->fw_info.default_display_engine_pll_frequency;
- else
- dp_ref_clk_khz = clk_mgr_base->clks.dispclk_khz;
-
- return dce_adjust_dp_ref_freq_for_ss(clk_mgr, dp_ref_clk_khz);
-}
-
-static void dce60_pplib_apply_display_requirements(
- struct dc *dc,
- struct dc_state *context)
-{
- struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
-
- dce110_fill_display_configs(context, pp_display_cfg);
-
- if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0)
- dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
-}
-
-static void dce60_update_clocks(struct clk_mgr *clk_mgr_base,
- struct dc_state *context,
- bool safe_to_lower)
-{
- struct clk_mgr_internal *clk_mgr_dce = TO_CLK_MGR_INTERNAL(clk_mgr_base);
- struct dm_pp_power_level_change_request level_change_req;
- const int max_disp_clk =
- clk_mgr_dce->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz;
- int patched_disp_clk = MIN(max_disp_clk, context->bw_ctx.bw.dce.dispclk_khz);
-
- level_change_req.power_level = dce_get_required_clocks_state(clk_mgr_base, context);
- /* get max clock state from PPLIB */
- if ((level_change_req.power_level < clk_mgr_dce->cur_min_clks_state && safe_to_lower)
- || level_change_req.power_level > clk_mgr_dce->cur_min_clks_state) {
- if (dm_pp_apply_power_level_change_request(clk_mgr_base->ctx, &level_change_req))
- clk_mgr_dce->cur_min_clks_state = level_change_req.power_level;
- }
-
- if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr_base->clks.dispclk_khz)) {
- patched_disp_clk = dce_set_clock(clk_mgr_base, patched_disp_clk);
- clk_mgr_base->clks.dispclk_khz = patched_disp_clk;
- }
- dce60_pplib_apply_display_requirements(clk_mgr_base->ctx->dc, context);
-}
-
-
-
-
-
-
-
-
-static struct clk_mgr_funcs dce60_funcs = {
- .get_dp_ref_clk_frequency = dce60_get_dp_ref_freq_khz,
- .update_clocks = dce60_update_clocks
-};
-
-void dce60_clk_mgr_construct(
- struct dc_context *ctx,
- struct clk_mgr_internal *clk_mgr)
-{
- struct clk_mgr *base = &clk_mgr->base;
-
- dce_clk_mgr_construct(ctx, clk_mgr);
-
- memcpy(clk_mgr->max_clks_by_state,
- dce60_max_clks_by_state,
- sizeof(dce60_max_clks_by_state));
-
- clk_mgr->regs = &disp_clk_regs;
- clk_mgr->clk_mgr_shift = &disp_clk_shift;
- clk_mgr->clk_mgr_mask = &disp_clk_mask;
- clk_mgr->base.funcs = &dce60_funcs;
-
- base->clks.max_supported_dispclk_khz =
- clk_mgr->max_clks_by_state[DM_PP_CLOCKS_STATE_PERFORMANCE].display_clk_khz;
-}
-
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
index e18097f82091..09e83097a623 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
@@ -740,7 +740,8 @@ void rn_clk_mgr_construct(
if (clk_mgr->base.dentist_vco_freq_khz == 0)
clk_mgr->base.dentist_vco_freq_khz = 3600000;
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) {
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) {
if (clk_mgr->periodic_retraining_disabled) {
rn_bw_params.wm_table = lpddr4_wm_table_with_disabled_ppt;
} else {
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
index b0aba3a6f13c..dcec9d0f8c34 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
@@ -421,10 +421,8 @@ static void dcn3_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
clk_mgr_base->bw_params->dc_mode_softmax_memclk = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_UCLK);
/* Refresh bounding box */
- DC_FP_START();
clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
clk_mgr->base.ctx->dc, clk_mgr_base->bw_params);
- DC_FP_END();
}
static bool dcn3_is_smu_present(struct clk_mgr *clk_mgr_base)
@@ -523,6 +521,7 @@ void dcn3_clk_mgr_construct(
struct pp_smu_funcs *pp_smu,
struct dccg *dccg)
{
+ (void)pp_smu;
struct clk_state_registers_and_bypass s = { 0 };
clk_mgr->base.ctx = ctx;
@@ -547,6 +546,7 @@ void dcn3_clk_mgr_construct(
/* in case we don't get a value from the register, use default */
if (clk_mgr->base.dentist_vco_freq_khz == 0)
clk_mgr->base.dentist_vco_freq_khz = 3650000;
+
/* Convert dprefclk units from MHz to KHz */
/* Value already divided by 10, some resolution lost */
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
index 7aee02d56292..57ba7bc4d16e 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn301/vg_clk_mgr.c
@@ -733,11 +733,12 @@ void vg_clk_mgr_construct(
if (clk_mgr->base.base.dentist_vco_freq_khz == 0)
clk_mgr->base.base.dentist_vco_freq_khz = 3600000;
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
vg_bw_params.wm_table = lpddr5_wm_table;
- } else {
+ else
vg_bw_params.wm_table = ddr4_wm_table;
- }
+
/* Saved clocks configured at boot for debug purposes */
vg_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
index 051052bd10c9..89fc482947ef 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
@@ -329,6 +329,9 @@ bool dcn31_are_clock_states_equal(struct dc_clocks *a,
static void dcn31_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
+ (void)regs_and_bypass;
+ (void)clk_mgr_base;
+ (void)log_info;
return;
}
@@ -725,11 +728,12 @@ void dcn31_clk_mgr_construct(
/* TODO: Check we get what we expect during bringup */
clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
dcn31_bw_params.wm_table = lpddr5_wm_table;
- } else {
+ else
dcn31_bw_params.wm_table = ddr5_wm_table;
- }
+
/* Saved clocks configured at boot for debug purposes */
dcn31_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
&clk_mgr->base.base, &log_info);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
index 0cb37827a62b..b08a70a2f571 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c
@@ -395,6 +395,9 @@ bool dcn314_are_clock_states_equal(struct dc_clocks *a,
static void dcn314_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
+ (void)regs_and_bypass;
+ (void)clk_mgr_base;
+ (void)log_info;
return;
}
@@ -842,7 +845,8 @@ void dcn314_clk_mgr_construct(
/* TODO: Check we get what we expect during bringup */
clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
dcn314_bw_params.wm_table = lpddr5_wm_table;
else
dcn314_bw_params.wm_table = ddr5_wm_table;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
index c49268db85f6..3a651c1a866d 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
@@ -247,6 +247,9 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
static void dcn315_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
+ (void)regs_and_bypass;
+ (void)clk_mgr_base;
+ (void)log_info;
return;
}
@@ -652,11 +655,12 @@ void dcn315_clk_mgr_construct(
if (clk_mgr->base.smu_ver > 0)
clk_mgr->base.smu_present = true;
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
dcn315_bw_params.wm_table = lpddr5_wm_table;
- } else {
+ else
dcn315_bw_params.wm_table = ddr5_wm_table;
- }
+
/* Saved clocks configured at boot for debug purposes */
dcn315_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
&clk_mgr->base.base, &log_info);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
index 1769b1f26e75..e9d492d8c8d4 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
@@ -255,6 +255,9 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base,
static void dcn316_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
+ (void)regs_and_bypass;
+ (void)clk_mgr_base;
+ (void)log_info;
return;
}
@@ -636,11 +639,12 @@ void dcn316_clk_mgr_construct(
clk_mgr->base.base.dentist_vco_freq_khz = 2500000; /* 2400MHz */
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
dcn316_bw_params.wm_table = lpddr5_wm_table;
- } else {
+ else
dcn316_bw_params.wm_table = ddr4_wm_table;
- }
+
/* Saved clocks configured at boot for debug purposes */
dcn316_dump_clk_registers(&clk_mgr->base.base.boot_snapshot,
&clk_mgr->base.base, &log_info);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
index 2856b0337e87..fda6cade30a8 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
@@ -872,6 +872,7 @@ static uint32_t dcn32_get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mg
static void dcn32_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
+ (void)log_info;
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
uint32_t dprefclk_did = 0;
uint32_t dcfclk_did = 0;
@@ -1059,11 +1060,9 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
if (!clk_mgr->dpm_present)
dcn32_patch_dpm_table(clk_mgr_base->bw_params);
- DC_FP_START();
/* Refresh bounding box */
clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
clk_mgr->base.ctx->dc, clk_mgr_base->bw_params);
- DC_FP_END();
}
static bool dcn32_are_clock_states_equal(struct dc_clocks *a,
@@ -1147,6 +1146,7 @@ void dcn32_clk_mgr_construct(
struct pp_smu_funcs *pp_smu,
struct dccg *dccg)
{
+ (void)pp_smu;
struct clk_log_info log_info = {0};
clk_mgr->base.ctx = ctx;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
index 6fc524752613..2798088842f4 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
@@ -1464,11 +1464,12 @@ void dcn35_clk_mgr_construct(
/* TODO: Check we get what we expect during bringup */
clk_mgr->base.base.dentist_vco_freq_khz = get_vco_frequency_from_reg(&clk_mgr->base);
- if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType) {
+ if (ctx->dc_bios->integrated_info &&
+ ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
dcn35_bw_params.wm_table = lpddr5_wm_table;
- } else {
+ else
dcn35_bw_params.wm_table = ddr5_wm_table;
- }
+
/* Saved clocks configured at boot for debug purposes */
dcn35_save_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c
index 604d256cb47a..9d8f81c3d3f0 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c
@@ -204,7 +204,7 @@ int dcn35_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispcl
khz_to_mhz_ceil(requested_dispclk_khz));
smu_print("requested_dispclk_khz = %d, actual_dispclk_set_mhz: %d\n", requested_dispclk_khz, actual_dispclk_set_mhz);
- return actual_dispclk_set_mhz * 1000;
+ return (int)((long long)actual_dispclk_set_mhz * 1000);
}
int dcn35_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
@@ -221,7 +221,7 @@ int dcn35_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr)
/* TODO: add code for programing DP DTO, currently this is down by command table */
- return actual_dprefclk_set_mhz * 1000;
+ return (int)((long long)actual_dprefclk_set_mhz * 1000);
}
int dcn35_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz)
@@ -238,7 +238,7 @@ int dcn35_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requeste
smu_print("requested_dcfclk_khz = %d, actual_dcfclk_set_mhz: %d\n", requested_dcfclk_khz, actual_dcfclk_set_mhz);
- return actual_dcfclk_set_mhz * 1000;
+ return (int)((long long)actual_dcfclk_set_mhz * 1000);
}
int dcn35_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz)
@@ -255,7 +255,7 @@ int dcn35_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int re
smu_print("requested_min_ds_dcfclk_khz = %d, actual_min_ds_dcfclk_mhz: %d\n", requested_min_ds_dcfclk_khz, actual_min_ds_dcfclk_mhz);
- return actual_min_ds_dcfclk_mhz * 1000;
+ return (int)((long long)actual_min_ds_dcfclk_mhz * 1000);
}
int dcn35_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz)
@@ -272,7 +272,7 @@ int dcn35_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz
smu_print("requested_dpp_khz = %d, actual_dppclk_set_mhz: %d\n", requested_dpp_khz, actual_dppclk_set_mhz);
- return actual_dppclk_set_mhz * 1000;
+ return (int)((long long)actual_dppclk_set_mhz * 1000);
}
void dcn35_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info)
@@ -424,7 +424,7 @@ int dcn35_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr)
0);
smu_print("%s: SMU DPREF clk = %d mhz\n", __func__, dprefclk);
- return dprefclk * 1000;
+ return (int)((long long)dprefclk * 1000);
}
int dcn35_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr)
@@ -439,7 +439,7 @@ int dcn35_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr)
0);
smu_print("%s: get_dtbclk = %dmhz\n", __func__, dtbclk);
- return dtbclk * 1000;
+ return (int)((long long)dtbclk * 1000);
}
/* Arg = 1: Turn DTB on; 0: Turn DTB CLK OFF. when it is on, it is 600MHZ */
void dcn35_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
index 03464f21d119..82c1a55a2271 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c
@@ -333,6 +333,7 @@ bool dcn401_is_dc_mode_present(struct clk_mgr *clk_mgr_base)
static void dcn401_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
struct clk_mgr *clk_mgr_base, struct clk_log_info *log_info)
{
+ (void)log_info;
struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
uint32_t dprefclk_did = 0;
uint32_t dcfclk_did = 0;
@@ -525,6 +526,7 @@ static void dcn401_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr
struct dc_state *context,
int ref_dtbclk_khz)
{
+ (void)ref_dtbclk_khz;
int i;
struct dccg *dccg = clk_mgr->dccg;
struct pipe_ctx *otg_master;
@@ -614,6 +616,7 @@ static void dcn401_update_clocks_update_dentist(
struct clk_mgr_internal *clk_mgr,
struct dc_state *context)
{
+ (void)context;
uint32_t new_disp_divider = 0;
uint32_t new_dispclk_wdivider = 0;
uint32_t dentist_dispclk_wdivider_readback = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c
new file mode 100644
index 000000000000..ec888aed207d
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.c
@@ -0,0 +1,1183 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dcn42_clk_mgr.h"
+
+#include "dccg.h"
+#include "clk_mgr_internal.h"
+
+// For dce12_get_dp_ref_freq_khz
+#include "dce100/dce_clk_mgr.h"
+
+// For dcn20_update_clocks_update_dpp_dto
+#include "dcn20/dcn20_clk_mgr.h"
+
+
+
+
+#include "reg_helper.h"
+#include "core_types.h"
+#include "dcn42_smu.h"
+#include "dm_helpers.h"
+
+/* TODO: remove this include once we ported over remaining clk mgr functions*/
+#include "dcn30/dcn30_clk_mgr.h"
+#include "dcn31/dcn31_clk_mgr.h"
+
+#include "dcn35/dcn35_clk_mgr.h"
+
+#include "dc_dmub_srv.h"
+#include "link_service.h"
+#include "logger_types.h"
+
+#include "clk/clk_15_0_0_offset.h"
+#include "clk/clk_15_0_0_sh_mask.h"
+#include "dcn/dcn_4_2_0_offset.h"
+#include "dcn/dcn_4_2_0_sh_mask.h"
+
+
+#undef DC_LOGGER
+#define DC_LOGGER \
+ dc_logger
+#define DC_LOGGER_INIT(logger) \
+ struct dal_logger *dc_logger = logger
+
+#undef FN
+#define FN(reg_name, field_name) \
+ clk_mgr->clk_mgr_shift->field_name, clk_mgr->clk_mgr_mask->field_name
+
+#define REG(reg) \
+ (clk_mgr->regs->reg)
+
+// for DCN register access
+#define DCN_BASE__INST0_SEG0 0x00000012
+#define DCN_BASE__INST0_SEG1 0x000000C0
+
+#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
+
+#define BASE(seg) BASE_INNER(seg)
+
+#define SR(reg_name) \
+ .reg_name = BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name
+
+// for CLKIP register access
+#define CLK_BASE__INST0_SEG0 0x00016C00
+
+#define CLK_BASE_INNER(seg) \
+ CLK_BASE__INST0_SEG ## seg
+
+#define CLK_SR_DCN42(reg_name) \
+ .reg_name = CLK_BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name
+
+static const struct clk_mgr_registers clk_mgr_regs_dcn42 = {
+ CLK_REG_LIST_DCN42()
+};
+
+static const struct clk_mgr_shift clk_mgr_shift_dcn42 = {
+ CLK_COMMON_MASK_SH_LIST_DCN42(__SHIFT)
+};
+
+static const struct clk_mgr_mask clk_mgr_mask_dcn42 = {
+ CLK_COMMON_MASK_SH_LIST_DCN42(_MASK)
+};
+
+#define TO_CLK_MGR_DCN42(clk_mgr_int)\
+ container_of(clk_mgr_int, struct clk_mgr_dcn42, base)
+
+bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context)
+{
+ int i, active_count = 0;
+
+ for (i = 0; i < context->stream_count; i++) {
+ const struct dc_stream_state *stream = context->streams[i];
+
+ /* Checking stream / link detection ensuring that PHY is active*/
+ if (dc_is_hdmi_signal(stream->signal) ||
+ dc_is_dvi_signal(stream->signal) ||
+ (dc_is_dp_signal(stream->signal) && !stream->dpms_off))
+ active_count++;
+ }
+
+ for (i = 0; i < dc->link_count; i++) {
+ const struct dc_link *link = dc->links[i];
+
+ /* abusing the fact that the dig and phy are coupled to see if the phy is enabled */
+ if (link->link_enc && link->link_enc->funcs->is_dig_enabled &&
+ link->link_enc->funcs->is_dig_enabled(link->link_enc))
+ active_count++;
+ }
+
+ return active_count > 0;
+}
+
+static uint32_t dcn42_get_clock_freq_from_clkip(struct clk_mgr *clk_mgr_base, enum clock_type clock)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ uint64_t clock_freq_mhz = 0;
+ uint32_t timer_threshold = 0;
+
+ // always safer to read the timer threshold instead of using cached value
+ REG_GET(CLK8_CLK_TICK_CNT_CONFIG_REG, TIMER_THRESHOLD, &timer_threshold);
+
+ if (timer_threshold == 0) {
+ BREAK_TO_DEBUGGER();
+ return 0;
+ }
+
+ switch (clock) {
+ case clock_type_dispclk:
+ clock_freq_mhz = REG_READ(CLK8_CLK0_CURRENT_CNT);
+ break;
+ case clock_type_dppclk:
+ clock_freq_mhz = REG_READ(CLK8_CLK1_CURRENT_CNT);
+ break;
+ case clock_type_dprefclk:
+ clock_freq_mhz = REG_READ(CLK8_CLK2_CURRENT_CNT);
+ break;
+ case clock_type_dcfclk:
+ clock_freq_mhz = REG_READ(CLK8_CLK3_CURRENT_CNT);
+ break;
+ case clock_type_dtbclk:
+ clock_freq_mhz = REG_READ(CLK8_CLK4_CURRENT_CNT);
+ break;
+ default:
+ break;
+ }
+
+ clock_freq_mhz *= DCN42_CLKIP_REFCLK;
+ clock_freq_mhz = div_u64(clock_freq_mhz, timer_threshold);
+
+ // there are no DCN clocks over 0xFFFFFFFF MHz
+ ASSERT(clock_freq_mhz <= 0xFFFFFFFF);
+
+ return (uint32_t)clock_freq_mhz;
+}
+
+void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
+ struct dc_state *context,
+ int ref_dtbclk_khz)
+{
+ (void)clk_mgr;
+ (void)context;
+ (void)ref_dtbclk_khz;
+ /* DCN42 does not implement set_dtbclk_dto function, so this is a no-op */
+}
+
+void dcn42_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr,
+ struct dc_state *context, bool safe_to_lower)
+{
+ int i;
+ bool dppclk_active[MAX_PIPES] = {0};
+
+
+ clk_mgr->dccg->ref_dppclk = clk_mgr->base.clks.dppclk_khz;
+ for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
+ int dpp_inst = 0, dppclk_khz, prev_dppclk_khz;
+
+ dppclk_khz = context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz;
+
+ if (context->res_ctx.pipe_ctx[i].plane_res.dpp)
+ dpp_inst = context->res_ctx.pipe_ctx[i].plane_res.dpp->inst;
+ else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz == 0) {
+ /* dpp == NULL && dppclk_khz == 0 is valid because of pipe harvesting.
+ * In this case just continue in loop
+ */
+ continue;
+ } else if (!context->res_ctx.pipe_ctx[i].plane_res.dpp && dppclk_khz > 0) {
+ /* The software state is not valid if dpp resource is NULL and
+ * dppclk_khz > 0.
+ */
+ ASSERT(false);
+ continue;
+ }
+
+ prev_dppclk_khz = clk_mgr->dccg->pipe_dppclk_khz[i];
+
+ if (safe_to_lower || prev_dppclk_khz < dppclk_khz)
+ clk_mgr->dccg->funcs->update_dpp_dto(
+ clk_mgr->dccg, dpp_inst, dppclk_khz);
+ dppclk_active[dpp_inst] = true;
+ }
+ if (safe_to_lower)
+ for (i = 0; i < clk_mgr->base.ctx->dc->res_pool->pipe_count; i++) {
+ struct dpp *old_dpp = clk_mgr->base.ctx->dc->current_state->res_ctx.pipe_ctx[i].plane_res.dpp;
+
+ if (old_dpp && !dppclk_active[old_dpp->inst])
+ clk_mgr->dccg->funcs->update_dpp_dto(clk_mgr->dccg, old_dpp->inst, 0);
+ }
+}
+
+void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
+ struct dc_state *context,
+ bool safe_to_lower)
+{
+ union dmub_rb_cmd cmd;
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
+ struct dc *dc = clk_mgr_base->ctx->dc;
+ bool update_dppclk = false;
+ bool update_dispclk = false;
+ bool dpp_clock_lowered = false;
+ bool has_active_display;
+
+ if (dc->work_arounds.skip_clock_update)
+ return;
+
+ has_active_display = dcn42_has_active_display(dc, context);
+
+ if (new_clocks->dtbclk_en && new_clocks->ref_dtbclk_khz < 590000)
+ new_clocks->ref_dtbclk_khz = 600000;
+ /*
+ * if it is safe to lower, but we are already in the lower state, we don't have to do anything
+ * also if safe to lower is false, we just go in the higher state
+ */
+ if (safe_to_lower) {
+ if (new_clocks->zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW &&
+ new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
+ dcn42_smu_set_zstate_support(clk_mgr, new_clocks->zstate_support);
+ clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
+ }
+
+ if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) {
+ if (clk_mgr->base.ctx->dc->config.allow_0_dtb_clk)
+ dcn42_smu_set_dtbclk(clk_mgr, false);
+ clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
+ }
+ /* check that we're not already in lower */
+ if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
+ /* if we can go lower, go lower */
+ if (has_active_display == false)
+ clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER;
+ }
+ } else {
+ if (new_clocks->zstate_support == DCN_ZSTATE_SUPPORT_DISALLOW &&
+ new_clocks->zstate_support != clk_mgr_base->clks.zstate_support) {
+ dcn42_smu_set_zstate_support(clk_mgr, DCN_ZSTATE_SUPPORT_DISALLOW);
+ clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
+ }
+ /* Only attempt to enable dtbclk if currently disabled AND new state requests it.
+ * 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;
+
+ dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
+ 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 = new_clocks->ref_dtbclk_khz;
+ clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
+ }
+ }
+
+ /* check that we're not already in D0 */
+ if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_MISSION_MODE) {
+ union display_idle_optimization_u idle_info = { 0 };
+
+ dcn42_smu_set_display_idle_optimization(clk_mgr, idle_info.data);
+ /* update power state */
+ clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_MISSION_MODE;
+ }
+ }
+ if (dc->debug.force_min_dcfclk_mhz > 0)
+ new_clocks->dcfclk_khz = (new_clocks->dcfclk_khz > (dc->debug.force_min_dcfclk_mhz * 1000)) ?
+ new_clocks->dcfclk_khz : (dc->debug.force_min_dcfclk_mhz * 1000);
+
+ if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr_base->clks.dcfclk_khz)) {
+ clk_mgr_base->clks.dcfclk_khz = new_clocks->dcfclk_khz;
+ clk_mgr_base->clks.fclk_khz = new_clocks->fclk_khz;
+ clk_mgr_base->clks.dramclk_khz = new_clocks->dramclk_khz;
+ dcn42_smu_set_hard_min_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_khz);
+ }
+
+ if (should_set_clock(safe_to_lower,
+ new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) {
+ clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
+
+ /* Clamp the requested clock to PMFW based on DCN limit. */
+ if (dc->debug.min_deep_sleep_dcfclk_khz > 0 && clk_mgr_base->clks.dcfclk_deep_sleep_khz < dc->debug.min_deep_sleep_dcfclk_khz)
+ clk_mgr_base->clks.dcfclk_deep_sleep_khz = dc->debug.min_deep_sleep_dcfclk_khz;
+
+ dcn42_smu_set_min_deep_sleep_dcfclk(clk_mgr, clk_mgr_base->clks.dcfclk_deep_sleep_khz);
+ }
+
+ // workaround: Limit dppclk to 100Mhz to avoid lower eDP panel switch to plus 4K monitor underflow.
+
+ if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->base.clks.dppclk_khz)) {
+ if (clk_mgr->base.clks.dppclk_khz > new_clocks->dppclk_khz)
+ dpp_clock_lowered = true;
+ clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz;
+ update_dppclk = true;
+ }
+
+ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) &&
+ (new_clocks->dispclk_khz > 0 || (safe_to_lower && has_active_display == false))) {
+ int requested_dispclk_khz = new_clocks->dispclk_khz;
+
+ dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true);
+
+ /* Clamp the requested clock to PMFW based on their limit. */
+ if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz)
+ requested_dispclk_khz = dc->debug.min_disp_clk_khz;
+
+ dcn42_smu_set_dispclk(clk_mgr, requested_dispclk_khz);
+ clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
+ dcn35_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false);
+
+ update_dispclk = true;
+ }
+
+ /* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */
+ if (!dc->debug.disable_dtb_ref_clk_switch && new_clocks->dtbclk_en &&
+ should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000,
+ clk_mgr_base->clks.ref_dtbclk_khz / 1000)) {
+ dcn42_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
+ clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz;
+ }
+
+ if (dpp_clock_lowered) {
+ // increase per DPP DTO before lowering global dppclk
+ dcn42_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
+ dcn42_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
+ } else {
+ // increase global DPPCLK before lowering per DPP DTO
+ if (update_dppclk || update_dispclk)
+ dcn42_smu_set_dppclk(clk_mgr, clk_mgr_base->clks.dppclk_khz);
+ dcn42_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower);
+ }
+ // notify DMCUB of latest clocks
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.notify_clocks.header.type = DMUB_CMD__CLK_MGR;
+ cmd.notify_clocks.header.sub_type = DMUB_CMD__CLK_MGR_NOTIFY_CLOCKS;
+ cmd.notify_clocks.clocks.dcfclk_khz = clk_mgr_base->clks.dcfclk_khz;
+ cmd.notify_clocks.clocks.dcfclk_deep_sleep_khz =
+ clk_mgr_base->clks.dcfclk_deep_sleep_khz;
+ cmd.notify_clocks.clocks.dispclk_khz = clk_mgr_base->clks.dispclk_khz;
+ cmd.notify_clocks.clocks.dppclk_khz = clk_mgr_base->clks.dppclk_khz;
+
+ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+}
+
+
+void dcn42_enable_pme_wa(struct clk_mgr *clk_mgr_base)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+ dcn42_smu_enable_pme_wa(clk_mgr);
+}
+
+
+bool dcn42_are_clock_states_equal(struct dc_clocks *a,
+ struct dc_clocks *b)
+{
+ if (a->dispclk_khz != b->dispclk_khz)
+ return false;
+ else if (a->dppclk_khz != b->dppclk_khz)
+ return false;
+ else if (a->dcfclk_khz != b->dcfclk_khz)
+ return false;
+ else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz)
+ return false;
+ else if (a->zstate_support != b->zstate_support)
+ return false;
+ else if (a->dtbclk_en != b->dtbclk_en)
+ return false;
+
+ return true;
+}
+
+static void dcn42_dump_clk_registers_internal(struct dcn42_clk_internal *internal, struct clk_mgr *clk_mgr_base)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+ REG_GET(CLK8_CLK_TICK_CNT_CONFIG_REG, TIMER_THRESHOLD, &internal->CLK8_CLK_TICK_CNT__TIMER_THRESHOLD);
+
+ // read dcf deep sleep divider
+ internal->CLK8_CLK0_DS_CNTL = REG_READ(CLK8_CLK0_DS_CNTL);
+ internal->CLK8_CLK3_DS_CNTL = REG_READ(CLK8_CLK3_DS_CNTL);
+ // read dispclk
+ internal->CLK8_CLK0_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dispclk);
+ internal->CLK8_CLK0_BYPASS_CNTL = REG_READ(CLK8_CLK0_BYPASS_CNTL);
+ // read dppclk
+ internal->CLK8_CLK1_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dppclk);
+ internal->CLK8_CLK1_BYPASS_CNTL = REG_READ(CLK8_CLK1_BYPASS_CNTL);
+ // read dprefclk
+ internal->CLK8_CLK2_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dprefclk);
+ internal->CLK8_CLK2_BYPASS_CNTL = REG_READ(CLK8_CLK2_BYPASS_CNTL);
+ // read dcfclk
+ internal->CLK8_CLK3_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dcfclk);
+ internal->CLK8_CLK3_BYPASS_CNTL = REG_READ(CLK8_CLK3_BYPASS_CNTL);
+ // read dtbclk
+ internal->CLK8_CLK4_CURRENT_CNT = dcn42_get_clock_freq_from_clkip(clk_mgr_base, clock_type_dtbclk);
+ internal->CLK8_CLK4_BYPASS_CNTL = REG_READ(CLK8_CLK4_BYPASS_CNTL);
+}
+
+static void dcn42_dump_clk_registers(struct clk_state_registers_and_bypass *regs_and_bypass,
+ struct clk_mgr_dcn42 *clk_mgr)
+{
+ struct dcn42_clk_internal internal = {0};
+ char *bypass_clks[5] = {"0x0 DFS", "0x1 REFCLK", "0x2 ERROR", "0x3 400 FCH", "0x4 600 FCH"};
+
+ DC_LOGGER_INIT(clk_mgr->base.base.ctx->logger);
+ (void)dc_logger;
+
+ dcn42_dump_clk_registers_internal(&internal, &clk_mgr->base.base);
+ regs_and_bypass->timer_threshold = internal.CLK8_CLK_TICK_CNT__TIMER_THRESHOLD;
+ regs_and_bypass->dcfclk = internal.CLK8_CLK3_CURRENT_CNT / 10;
+ regs_and_bypass->dcf_deep_sleep_divider = internal.CLK8_CLK3_DS_CNTL / 10;
+ regs_and_bypass->dcf_deep_sleep_allow = internal.CLK8_CLK3_DS_CNTL & 0x10; /*bit 4: CLK0_ALLOW_DS*/
+ regs_and_bypass->dprefclk = internal.CLK8_CLK2_CURRENT_CNT / 10;
+ regs_and_bypass->dispclk = internal.CLK8_CLK0_CURRENT_CNT / 10;
+ regs_and_bypass->dppclk = internal.CLK8_CLK1_CURRENT_CNT / 10;
+ regs_and_bypass->dtbclk = internal.CLK8_CLK4_CURRENT_CNT / 10;
+
+ regs_and_bypass->dispclk_bypass = get_reg_field_value(internal.CLK8_CLK0_BYPASS_CNTL, CLK8_CLK0_BYPASS_CNTL, CLK0_BYPASS_SEL);
+ regs_and_bypass->dppclk_bypass = get_reg_field_value(internal.CLK8_CLK1_BYPASS_CNTL, CLK8_CLK1_BYPASS_CNTL, CLK1_BYPASS_SEL);
+ regs_and_bypass->dprefclk_bypass = get_reg_field_value(internal.CLK8_CLK2_BYPASS_CNTL, CLK8_CLK2_BYPASS_CNTL, CLK2_BYPASS_SEL);
+ regs_and_bypass->dcfclk_bypass = get_reg_field_value(internal.CLK8_CLK3_BYPASS_CNTL, CLK8_CLK3_BYPASS_CNTL, CLK3_BYPASS_SEL);
+
+ if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) {
+ DC_LOG_SMU("clk_type,clk_value,deepsleep_cntl,deepsleep_allow,bypass\n");
+
+ DC_LOG_SMU("dcfclk,%d,%d,%d,%s\n",
+ regs_and_bypass->dcfclk,
+ regs_and_bypass->dcf_deep_sleep_divider,
+ regs_and_bypass->dcf_deep_sleep_allow,
+ bypass_clks[(int) regs_and_bypass->dcfclk_bypass]);
+
+ DC_LOG_SMU("dprefclk,%d,N/A,N/A,%s\n",
+ regs_and_bypass->dprefclk,
+ bypass_clks[(int) regs_and_bypass->dprefclk_bypass]);
+
+ DC_LOG_SMU("dispclk,%d,N/A,N/A,%s\n",
+ regs_and_bypass->dispclk,
+ bypass_clks[(int) regs_and_bypass->dispclk_bypass]);
+
+ //split
+ DC_LOG_SMU("SPLIT\n");
+
+ // REGISTER VALUES
+ DC_LOG_SMU("reg_name,value,clk_type\n");
+ DC_LOG_SMU("CLK1_CLK3_CURRENT_CNT,%d,dcfclk\n",
+ internal.CLK8_CLK3_CURRENT_CNT);
+
+ DC_LOG_SMU("CLK1_CLK3_DS_CNTL,%d,dcf_deep_sleep_divider\n",
+ internal.CLK8_CLK3_DS_CNTL);
+
+ DC_LOG_SMU("CLK1_CLK3_ALLOW_DS,%d,dcf_deep_sleep_allow\n",
+ (internal.CLK8_CLK3_DS_CNTL & 0x10));
+
+ DC_LOG_SMU("CLK1_CLK2_CURRENT_CNT,%d,dprefclk\n",
+ internal.CLK8_CLK2_CURRENT_CNT);
+
+ DC_LOG_SMU("CLK1_CLK0_CURRENT_CNT,%d,dispclk\n",
+ internal.CLK8_CLK0_CURRENT_CNT);
+
+ DC_LOG_SMU("CLK1_CLK1_CURRENT_CNT,%d,dppclk\n",
+ internal.CLK8_CLK1_CURRENT_CNT);
+
+ DC_LOG_SMU("CLK1_CLK4_CURRENT_CNT,%d,dtbclk\n",
+ internal.CLK8_CLK4_CURRENT_CNT);
+
+ DC_LOG_SMU("CLK1_CLK3_BYPASS_CNTL,%d,dcfclk_bypass\n",
+ internal.CLK8_CLK3_BYPASS_CNTL);
+
+ DC_LOG_SMU("CLK1_CLK2_BYPASS_CNTL,%d,dprefclk_bypass\n",
+ internal.CLK8_CLK2_BYPASS_CNTL);
+
+ DC_LOG_SMU("CLK1_CLK0_BYPASS_CNTL,%d,dispclk_bypass\n",
+ internal.CLK8_CLK0_BYPASS_CNTL);
+
+ DC_LOG_SMU("CLK1_CLK1_BYPASS_CNTL,%d,dppclk_bypass\n",
+ internal.CLK8_CLK1_BYPASS_CNTL);
+ }
+}
+
+bool dcn42_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ struct dc_context *ctx = clk_mgr->base.ctx;
+
+
+ if (ctx->dc->config.ignore_dpref_ss) {
+ /*revert bios's ss info for test only*/
+ return (clk_mgr->dprefclk_ss_percentage == 0);
+ }
+ /*need to update after BU*/
+ return false;
+}
+
+static void init_clk_states(struct clk_mgr *clk_mgr)
+{
+ uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz;
+
+ memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
+
+ clk_mgr->clks.dtbclk_en = true; // request DTBCLK disable on first commit
+ clk_mgr->clks.ref_dtbclk_khz = ref_dtbclk; // restore ref_dtbclk
+ clk_mgr->clks.p_state_change_support = true;
+ clk_mgr->clks.prev_p_state_change_support = true;
+ clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN;
+ clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN;
+}
+
+void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr,
+ struct dcn42_smu_dpm_clks *smu_dpm_clks)
+{
+ DpmClocks_t_dcn42 *table = smu_dpm_clks->dpm_clks;
+
+ if (!clk_mgr->smu_ver)
+ return;
+
+ if (!table || smu_dpm_clks->mc_address.quad_part == 0)
+ return;
+
+ memset(table, 0, sizeof(*table));
+
+ dcn42_smu_set_dram_addr_high(clk_mgr,
+ smu_dpm_clks->mc_address.high_part);
+ dcn42_smu_set_dram_addr_low(clk_mgr,
+ smu_dpm_clks->mc_address.low_part);
+ dcn42_smu_transfer_dpm_table_smu_2_dram(clk_mgr);
+}
+
+void dcn42_init_single_clock(unsigned int *entry_0,
+ uint32_t *smu_entry_0,
+ uint8_t num_levels)
+{
+ int i;
+ char *entry_i = (char *)entry_0;
+
+ ASSERT(num_levels <= MAX_NUM_DPM_LVL);
+ if (num_levels > MAX_NUM_DPM_LVL)
+ num_levels = MAX_NUM_DPM_LVL;
+
+
+ for (i = 0; i < num_levels; i++) {
+ *((unsigned int *)entry_i) = smu_entry_0[i];
+ entry_i += sizeof(struct clk_limit_table_entry);
+ }
+}
+
+unsigned int dcn42_convert_wck_ratio(uint8_t wck_ratio)
+{
+ switch (wck_ratio) {
+ case WCK_RATIO_1_2:
+ return 2;
+
+ case WCK_RATIO_1_4:
+ return 4;
+
+ default:
+ break;
+ }
+
+ return 1;
+}
+
+void dcn42_init_clocks(struct clk_mgr *clk_mgr_base)
+{
+ struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ struct clk_mgr_dcn42 *clk_mgr = TO_CLK_MGR_DCN42(clk_mgr_int);
+
+ DC_LOGGER_INIT(clk_mgr_base->ctx->logger);
+ (void)dc_logger;
+
+ init_clk_states(clk_mgr_base);
+
+ // to adjust dp_dto reference clock if ssc is enable otherwise to apply dprefclk
+ if (dcn42_is_spll_ssc_enabled(clk_mgr_base))
+ clk_mgr_base->dp_dto_source_clock_in_khz =
+ dce_adjust_dp_ref_freq_for_ss(clk_mgr_int, clk_mgr_base->dprefclk_khz);
+ else
+ clk_mgr_base->dp_dto_source_clock_in_khz = clk_mgr_base->dprefclk_khz;
+
+ DC_LOG_SMU("dp_dto_source_clock %d, dprefclk %d\n", clk_mgr_base->dp_dto_source_clock_in_khz, clk_mgr_base->dprefclk_khz);
+ dcn42_dump_clk_registers(&clk_mgr_base->boot_snapshot, clk_mgr);
+
+ clk_mgr_base->clks.ref_dtbclk_khz = clk_mgr_base->boot_snapshot.dtbclk * 10;
+ clk_mgr_base->clks.dtbclk_en = clk_mgr_base->boot_snapshot.dtbclk > 59000;
+}
+
+static struct clk_bw_params dcn42_bw_params = {
+ .vram_type = Ddr4MemType,
+ .num_channels = 1,
+ .clk_table = {
+ .num_entries = 4,
+ },
+
+};
+
+static struct wm_table ddr5_wm_table = {
+ .entries = {
+ {
+ .wm_inst = WM_A,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.72,
+ .sr_exit_time_us = 28.0,
+ .sr_enter_plus_exit_time_us = 30.0,
+ .valid = true,
+ },
+ {
+ .wm_inst = WM_B,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.72,
+ .sr_exit_time_us = 28.0,
+ .sr_enter_plus_exit_time_us = 30.0,
+ .valid = true,
+ },
+ {
+ .wm_inst = WM_C,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.72,
+ .sr_exit_time_us = 28.0,
+ .sr_enter_plus_exit_time_us = 30.0,
+ .valid = true,
+ },
+ {
+ .wm_inst = WM_D,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.72,
+ .sr_exit_time_us = 28.0,
+ .sr_enter_plus_exit_time_us = 30.0,
+ .valid = true,
+ },
+ }
+};
+
+static struct wm_table lpddr5_wm_table = {
+ .entries = {
+ {
+ .wm_inst = WM_A,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.65333,
+ .sr_exit_time_us = 28.0,
+ .sr_enter_plus_exit_time_us = 30.0,
+ .valid = true,
+ },
+ {
+ .wm_inst = WM_B,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.65333,
+ .sr_exit_time_us = 28.0,
+ .sr_enter_plus_exit_time_us = 30.0,
+ .valid = true,
+ },
+ {
+ .wm_inst = WM_C,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.65333,
+ .sr_exit_time_us = 28.0,
+ .sr_enter_plus_exit_time_us = 30.0,
+ .valid = true,
+ },
+ {
+ .wm_inst = WM_D,
+ .wm_type = WM_TYPE_PSTATE_CHG,
+ .pstate_latency_us = 11.65333,
+ .sr_exit_time_us = 28.0,
+ .sr_enter_plus_exit_time_us = 30.0,
+ .valid = true,
+ },
+ }
+};
+
+struct dcn42_ss_info_table dcn42_ss_info_table = {
+ .ss_divider = 1000,
+ .ss_percentage = {0, 0, 375, 375, 375}
+};
+
+static void dcn42_read_ss_info_from_lut(struct clk_mgr_internal *clk_mgr)
+{
+ uint32_t clock_source;
+
+ clock_source = (REG_READ(CLK8_CLK2_BYPASS_CNTL) & CLK8_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL_MASK);
+ // If it's DFS mode, clock_source is 0.
+ if (dcn42_is_spll_ssc_enabled(&clk_mgr->base) && (clock_source < ARRAY_SIZE(dcn42_ss_info_table.ss_percentage))) {
+ clk_mgr->dprefclk_ss_percentage = dcn42_ss_info_table.ss_percentage[clock_source];
+
+ if (clk_mgr->dprefclk_ss_percentage != 0) {
+ clk_mgr->ss_on_dprefclk = true;
+ clk_mgr->dprefclk_ss_divider = dcn42_ss_info_table.ss_divider;
+ }
+ }
+}
+
+void dcn42_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn42_watermarks *table)
+{
+ int i, num_valid_sets;
+
+ num_valid_sets = 0;
+
+ for (i = 0; i < WM_SET_COUNT; i++) {
+ /* skip empty entries, the smu array has no holes*/
+ if (!bw_params->wm_table.entries[i].valid)
+ continue;
+
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmSetting = bw_params->wm_table.entries[i].wm_inst;
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType = bw_params->wm_table.entries[i].wm_type;
+ /* We will not select WM based on fclk, so leave it as unconstrained */
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0;
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF;
+
+ if (table->WatermarkRow[WM_DCFCLK][num_valid_sets].WmType == WM_TYPE_PSTATE_CHG) {
+ if (i == 0)
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk = 0;
+ else {
+ /* add 1 to make it non-overlapping with next lvl */
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinMclk =
+ bw_params->clk_table.entries[i - 1].dcfclk_mhz + 1;
+ }
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxMclk =
+ bw_params->clk_table.entries[i].dcfclk_mhz;
+
+ } else {
+ /* unconstrained for memory retraining */
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MinClock = 0;
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets].MaxClock = 0xFFFF;
+
+ /* Modify previous watermark range to cover up to max */
+ if (num_valid_sets > 0)
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF;
+ }
+ num_valid_sets++;
+ }
+
+ ASSERT(num_valid_sets != 0); /* Must have at least one set of valid watermarks */
+
+ /* modify the min and max to make sure we cover the whole range*/
+ table->WatermarkRow[WM_DCFCLK][0].MinMclk = 0;
+ table->WatermarkRow[WM_DCFCLK][0].MinClock = 0;
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxMclk = 0xFFFF;
+ table->WatermarkRow[WM_DCFCLK][num_valid_sets - 1].MaxClock = 0xFFFF;
+
+ /* This is for writeback only, does not matter currently as no writeback support*/
+ table->WatermarkRow[WM_SOCCLK][0].WmSetting = WM_A;
+ table->WatermarkRow[WM_SOCCLK][0].MinClock = 0;
+ table->WatermarkRow[WM_SOCCLK][0].MaxClock = 0xFFFF;
+ table->WatermarkRow[WM_SOCCLK][0].MinMclk = 0;
+ table->WatermarkRow[WM_SOCCLK][0].MaxMclk = 0xFFFF;
+}
+
+void dcn42_notify_wm_ranges(struct clk_mgr *clk_mgr_base)
+{
+ int i = 0;
+ struct dcn42_watermarks *table = NULL;
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ struct clk_mgr_dcn42 *clk_mgr_dcn42 = TO_CLK_MGR_DCN42(clk_mgr);
+
+ if (!clk_mgr->smu_ver)
+ return;
+ /*send once already skip*/
+ if (clk_mgr_base->bw_params->wm_table.entries[WM_A].valid == true)
+ return;
+ clk_mgr_dcn42->smu_wm_set.wm_set = (struct dcn42_watermarks *)dm_helpers_allocate_gpu_mem(
+ clk_mgr->base.ctx,
+ DC_MEM_ALLOC_TYPE_GART,
+ sizeof(struct dcn42_watermarks),
+ &clk_mgr_dcn42->smu_wm_set.mc_address.quad_part);
+
+ ASSERT(clk_mgr_dcn42->smu_wm_set.wm_set);
+
+ table = clk_mgr_dcn42->smu_wm_set.wm_set;
+
+ if (!table || clk_mgr_dcn42->smu_wm_set.mc_address.quad_part == 0)
+ return;
+
+ memset(table, 0, sizeof(*table));
+ /*same as previous asic, set wm valid before building watermark ranges*/
+ for (i = 0; i < WM_SET_COUNT; i++) {
+ clk_mgr_base->bw_params->wm_table.entries[i].wm_inst = i;
+
+ if (i >= clk_mgr_base->bw_params->clk_table.num_entries) {
+ clk_mgr_base->bw_params->wm_table.entries[i].valid = false;
+ continue;
+ }
+ clk_mgr_base->bw_params->wm_table.entries[i].wm_type = WM_TYPE_PSTATE_CHG;
+ clk_mgr_base->bw_params->wm_table.entries[i].valid = true;
+ }
+ /* build watermark_range will check this valid range*/
+ dcn42_build_watermark_ranges(clk_mgr_base->bw_params, table);
+
+ dcn42_smu_set_dram_addr_high(clk_mgr,
+ clk_mgr_dcn42->smu_wm_set.mc_address.high_part);
+ dcn42_smu_set_dram_addr_low(clk_mgr,
+ clk_mgr_dcn42->smu_wm_set.mc_address.low_part);
+ dcn42_smu_transfer_wm_table_dram_2_smu(clk_mgr);
+
+ if (clk_mgr_dcn42->smu_wm_set.wm_set && clk_mgr_dcn42->smu_wm_set.mc_address.quad_part != 0)
+ dm_helpers_free_gpu_mem(clk_mgr->base.ctx, DC_MEM_ALLOC_TYPE_GART,
+ clk_mgr_dcn42->smu_wm_set.wm_set);
+
+}
+
+void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base)
+{
+ struct dc *dc = clk_mgr_base->ctx->dc;
+ struct dc_state *context = dc->current_state;
+
+ if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
+ /* if we can go lower, go lower */
+ if (dcn42_has_active_display(dc, context) == false)
+ clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER;
+ }
+
+ if (clk_mgr_base->clks.pwr_state == DCN_PWR_STATE_LOW_POWER) {
+ union display_idle_optimization_u idle_info = { 0 };
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+ idle_info.idle_info.df_request_disabled = 1;
+ idle_info.idle_info.phy_ref_clk_off = 1;
+ idle_info.idle_info.s0i2_rdy = 1;
+ dcn42_smu_set_display_idle_optimization(clk_mgr, idle_info.data);
+ }
+}
+
+void dcn42_exit_low_power_state(struct clk_mgr *clk_mgr_base)
+{
+ (void)clk_mgr_base;
+
+}
+
+static void dcn42_init_clocks_fpga(struct clk_mgr *clk_mgr)
+{
+ init_clk_states(clk_mgr);
+
+}
+
+void dcn42_update_clocks_fpga(struct clk_mgr *clk_mgr,
+ struct dc_state *context,
+ bool safe_to_lower)
+{
+ struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr);
+ struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk;
+ int fclk_adj = new_clocks->fclk_khz;
+
+ /* TODO: remove this after correctly set by DML */
+ new_clocks->dcfclk_khz = 400000;
+ new_clocks->socclk_khz = 400000;
+
+ /* Min fclk = 1.2GHz since all the extra scemi logic seems to run off of it */
+ //int fclk_adj = new_clocks->fclk_khz > 1200000 ? new_clocks->fclk_khz : 1200000;
+ new_clocks->fclk_khz = 4320000;
+
+ if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, clk_mgr->clks.phyclk_khz))
+ clk_mgr->clks.phyclk_khz = new_clocks->phyclk_khz;
+
+ if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, clk_mgr->clks.dcfclk_khz))
+ clk_mgr->clks.dcfclk_khz = new_clocks->dcfclk_khz;
+
+ if (should_set_clock(safe_to_lower,
+ new_clocks->dcfclk_deep_sleep_khz, clk_mgr->clks.dcfclk_deep_sleep_khz))
+ clk_mgr->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz;
+
+ if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr->clks.socclk_khz))
+ clk_mgr->clks.socclk_khz = new_clocks->socclk_khz;
+
+ if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr->clks.dramclk_khz))
+ clk_mgr->clks.dramclk_khz = new_clocks->dramclk_khz;
+
+ if (should_set_clock(safe_to_lower, new_clocks->dppclk_khz, clk_mgr->clks.dppclk_khz))
+ clk_mgr->clks.dppclk_khz = new_clocks->dppclk_khz;
+
+ if (should_set_clock(safe_to_lower, fclk_adj, clk_mgr->clks.fclk_khz))
+ clk_mgr->clks.fclk_khz = fclk_adj;
+
+ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr->clks.dispclk_khz))
+ clk_mgr->clks.dispclk_khz = new_clocks->dispclk_khz;
+
+ /* Both fclk and ref_dppclk run on the same scemi clock.
+ * So take the higher value since the DPP DTO is typically programmed
+ * such that max dppclk is 1:1 with ref_dppclk.
+ */
+ if (clk_mgr->clks.fclk_khz > clk_mgr->clks.dppclk_khz)
+ clk_mgr->clks.dppclk_khz = clk_mgr->clks.fclk_khz;
+ if (clk_mgr->clks.dppclk_khz > clk_mgr->clks.fclk_khz)
+ clk_mgr->clks.fclk_khz = clk_mgr->clks.dppclk_khz;
+
+ // Both fclk and ref_dppclk run on the same scemi clock.
+ clk_mgr_int->dccg->ref_dppclk = clk_mgr->clks.fclk_khz;
+
+ dm_set_dcn_clocks(clk_mgr->ctx, &clk_mgr->clks);
+ if (clk_mgr->clks.dtbclk_en) {
+ dcn42_update_clocks_update_dtb_dto(clk_mgr_int, context, clk_mgr->clks.ref_dtbclk_khz);
+ } else {
+ clk_mgr->clks.ref_dtbclk_khz = 0;
+ }
+ dcn42_update_clocks_update_dpp_dto(clk_mgr_int, context, safe_to_lower);
+}
+
+unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+
+ unsigned int num_clk_levels;
+
+ switch (clk_type) {
+ case CLK_TYPE_DISPCLK:
+ num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dispclk_levels;
+ return num_clk_levels ?
+ clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dispclk_mhz * 1000 :
+ clk_mgr->base.boot_snapshot.dispclk;
+ case CLK_TYPE_DPPCLK:
+ num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dppclk_levels;
+ return num_clk_levels ?
+ clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dppclk_mhz * 1000 :
+ clk_mgr->base.boot_snapshot.dppclk;
+ case CLK_TYPE_DSCCLK:
+ num_clk_levels = clk_mgr->base.bw_params->clk_table.num_entries_per_clk.num_dispclk_levels;
+ return num_clk_levels ?
+ clk_mgr->base.bw_params->clk_table.entries[num_clk_levels - 1].dispclk_mhz * 1000 / 3 :
+ clk_mgr->base.boot_snapshot.dispclk / 3;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int dcn42_get_dispclk_from_dentist(struct clk_mgr *clk_mgr_base)
+{
+ (void)clk_mgr_base;
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ uint32_t dispclk_wdivider;
+ int disp_divider;
+
+ REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, &dispclk_wdivider);
+ disp_divider = dentist_get_divider_from_did(dispclk_wdivider);
+
+ /* Return DISPCLK freq in Khz */
+ if (disp_divider)
+ return (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / disp_divider;
+
+ return 0;
+}
+bool dcn42_is_smu_present(struct clk_mgr *clk_mgr_base)
+{
+ struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+ return clk_mgr->smu_present;
+}
+
+void dcn42_get_smu_clocks(struct clk_mgr_internal *clk_mgr_int)
+{
+ struct clk_mgr *clk_mgr_base = &clk_mgr_int->base;
+ struct dcn42_smu_dpm_clks smu_dpm_clks = { 0 };
+
+ DC_LOGGER_INIT(clk_mgr_base->ctx->logger);
+ (void)dc_logger;
+
+ smu_dpm_clks.dpm_clks = (DpmClocks_t_dcn42 *)dm_helpers_allocate_gpu_mem(
+ clk_mgr_base->ctx,
+ DC_MEM_ALLOC_TYPE_GART,
+ sizeof(DpmClocks_t_dcn42),
+ &smu_dpm_clks.mc_address.quad_part);
+
+ ASSERT(smu_dpm_clks.dpm_clks);
+ if (clk_mgr_base->ctx->dc->debug.pstate_enabled && smu_dpm_clks.mc_address.quad_part != 0) {
+ int i;
+ DpmClocks_t_dcn42 *dpm_clks = smu_dpm_clks.dpm_clks;
+
+ dcn42_get_dpm_table_from_smu(clk_mgr_int, &smu_dpm_clks);
+ DC_LOG_SMU("NumDcfClkLevelsEnabled: %d\n"
+ "NumDispClkLevelsEnabled: %d\n"
+ "NumSocClkLevelsEnabled: %d\n"
+ "VcnClkLevelsEnabled: %d\n"
+ "FClkLevelsEnabled: %d\n"
+ "NumMemPstatesEnabled: %d\n"
+ "MinGfxClk: %d\n"
+ "MaxGfxClk: %d\n",
+ dpm_clks->NumDcfClkLevelsEnabled,
+ dpm_clks->NumDispClkLevelsEnabled,
+ dpm_clks->NumSocClkLevelsEnabled,
+ dpm_clks->VcnClkLevelsEnabled,
+ dpm_clks->NumFclkLevelsEnabled,
+ dpm_clks->NumMemPstatesEnabled,
+ dpm_clks->MinGfxClk,
+ dpm_clks->MaxGfxClk);
+
+ for (i = 0; i < NUM_DCFCLK_DPM_LEVELS; i++) {
+ DC_LOG_SMU("dpm_clks->DcfClocks[%d] = %d\n",
+ i,
+ dpm_clks->DcfClocks[i]);
+ }
+ for (i = 0; i < NUM_DISPCLK_DPM_LEVELS; i++) {
+ DC_LOG_SMU("dpm_clks->DispClocks[%d] = %d\n",
+ i, dpm_clks->DispClocks[i]);
+ }
+ for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) {
+ DC_LOG_SMU("dpm_clks->SocClocks[%d] = %d\n",
+ i, dpm_clks->SocClocks[i]);
+ }
+ for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) {
+ DC_LOG_SMU("dpm_clks->FclkClocks_Freq[%d] = %d\n",
+ i, dpm_clks->FclkClocks_Freq[i]);
+ DC_LOG_SMU("dpm_clks->FclkClocks_Voltage[%d] = %d\n",
+ i, dpm_clks->FclkClocks_Voltage[i]);
+ }
+ for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++)
+ DC_LOG_SMU("dpm_clks->SocVoltage[%d] = %d\n",
+ i, dpm_clks->SocVoltage[i]);
+
+ for (i = 0; i < NUM_MEM_PSTATE_LEVELS; i++) {
+ DC_LOG_SMU("dpm_clks.MemPstateTable[%d].UClk = %d\n"
+ "dpm_clks->MemPstateTable[%d].MemClk= %d\n"
+ "dpm_clks->MemPstateTable[%d].Voltage = %d\n",
+ i, dpm_clks->MemPstateTable[i].UClk,
+ i, dpm_clks->MemPstateTable[i].MemClk,
+ i, dpm_clks->MemPstateTable[i].Voltage);
+ }
+
+ if (clk_mgr_base->ctx->dc_bios->integrated_info && clk_mgr_base->ctx->dc->config.use_default_clock_table == false) {
+ /* DCFCLK */
+ dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz,
+ dpm_clks->DcfClocks,
+ dpm_clks->NumDcfClkLevelsEnabled);
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels = dpm_clks->NumDcfClkLevelsEnabled;
+
+ /* SOCCLK */
+ dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz,
+ dpm_clks->SocClocks,
+ dpm_clks->NumSocClkLevelsEnabled);
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_socclk_levels = dpm_clks->NumSocClkLevelsEnabled;
+
+ /* DISPCLK */
+ dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz,
+ dpm_clks->DispClocks,
+ dpm_clks->NumDispClkLevelsEnabled);
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels = dpm_clks->NumDispClkLevelsEnabled;
+
+ /* DPPCLK */
+ dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].dppclk_mhz,
+ dpm_clks->DppClocks,
+ dpm_clks->NumDispClkLevelsEnabled);
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dppclk_levels = dpm_clks->NumDispClkLevelsEnabled;
+
+ /* FCLK */
+ dcn42_init_single_clock(&clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz,
+ dpm_clks->FclkClocks_Freq,
+ NUM_FCLK_DPM_LEVELS);
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_fclk_levels = dpm_clks->NumFclkLevelsEnabled;
+ clk_mgr_base->bw_params->clk_table.num_entries = dpm_clks->NumFclkLevelsEnabled;
+
+ /* Memory Pstate table is in reverse order*/
+ ASSERT(dpm_clks->NumMemPstatesEnabled <= NUM_MEM_PSTATE_LEVELS);
+ if (dpm_clks->NumMemPstatesEnabled > NUM_MEM_PSTATE_LEVELS)
+ dpm_clks->NumMemPstatesEnabled = NUM_MEM_PSTATE_LEVELS;
+ for (i = 0; i < dpm_clks->NumMemPstatesEnabled; i++) {
+ clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].memclk_mhz = dpm_clks->MemPstateTable[i].MemClk;
+ clk_mgr_base->bw_params->clk_table.entries[dpm_clks->NumMemPstatesEnabled - 1 - i].wck_ratio = dcn42_convert_wck_ratio(dpm_clks->MemPstateTable[i].WckRatio) ;
+ }
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels = dpm_clks->NumMemPstatesEnabled;
+
+ /* DTBCLK*/
+ clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz = 600; /* Fixed on platform */
+ clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels = 1;
+ }
+ }
+ if (smu_dpm_clks.dpm_clks && smu_dpm_clks.mc_address.quad_part != 0)
+ dm_helpers_free_gpu_mem(clk_mgr_base->ctx, DC_MEM_ALLOC_TYPE_GART,
+ smu_dpm_clks.dpm_clks);
+}
+
+static struct clk_mgr_funcs dcn42_funcs = {
+ .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
+ .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz,
+ .update_clocks = dcn42_update_clocks,
+ .init_clocks = dcn42_init_clocks,
+ .enable_pme_wa = dcn42_enable_pme_wa,
+ .are_clock_states_equal = dcn42_are_clock_states_equal,
+ .notify_wm_ranges = dcn42_notify_wm_ranges,
+ .set_low_power_state = dcn42_set_low_power_state,
+ .exit_low_power_state = dcn42_exit_low_power_state,
+ .get_max_clock_khz = dcn42_get_max_clock_khz,
+ .get_dispclk_from_dentist = dcn42_get_dispclk_from_dentist,
+ .is_smu_present = dcn42_is_smu_present,
+};
+
+struct clk_mgr_funcs dcn42_fpga_funcs = {
+ .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
+ .update_clocks = dcn42_update_clocks_fpga,
+ .init_clocks = dcn42_init_clocks_fpga,
+ .get_dtb_ref_clk_frequency = dcn31_get_dtb_ref_freq_khz,
+};
+
+void dcn42_clk_mgr_construct(
+ struct dc_context *ctx,
+ struct clk_mgr_dcn42 *clk_mgr,
+ struct pp_smu_funcs *pp_smu,
+ struct dccg *dccg)
+{
+ clk_mgr->base.base.ctx = ctx;
+ clk_mgr->base.base.funcs = &dcn42_funcs;
+ clk_mgr->base.regs = &clk_mgr_regs_dcn42;
+ clk_mgr->base.clk_mgr_shift = &clk_mgr_shift_dcn42;
+ clk_mgr->base.clk_mgr_mask = &clk_mgr_mask_dcn42;
+
+ clk_mgr->base.pp_smu = pp_smu;
+
+ clk_mgr->base.dccg = dccg;
+ clk_mgr->base.dfs_bypass_disp_clk = 0;
+
+ clk_mgr->base.dprefclk_ss_percentage = 0;
+ clk_mgr->base.dprefclk_ss_divider = 1000;
+ clk_mgr->base.ss_on_dprefclk = false;
+ clk_mgr->base.dfs_ref_freq_khz = 48000; /*sync with pmfw*/
+ clk_mgr->base.base.clks.ref_dtbclk_khz = 600000;
+
+ /* Changed from DCN3.2_clock_frequency doc to match
+ * dcn32_dump_clk_registers from 4 * dentist_vco_freq_khz /
+ * dprefclk DID divider
+ */
+ clk_mgr->base.base.dprefclk_khz = 600000;
+
+ clk_mgr->base.smu_present = false;
+ clk_mgr->base.smu_ver = dcn42_smu_get_pmfw_version(&clk_mgr->base);
+ if (clk_mgr->base.smu_ver && clk_mgr->base.smu_ver != -1)
+ clk_mgr->base.smu_present = true;
+
+ if (ctx->dc_bios->integrated_info) {
+ clk_mgr->base.base.dentist_vco_freq_khz = ctx->dc_bios->integrated_info->dentist_vco_freq;
+
+ if (ctx->dc_bios->integrated_info->memory_type == LpDdr5MemType)
+ dcn42_bw_params.wm_table = lpddr5_wm_table;
+ else
+ dcn42_bw_params.wm_table = ddr5_wm_table;
+ dcn42_bw_params.vram_type = ctx->dc_bios->integrated_info->memory_type;
+ dcn42_bw_params.dram_channel_width_bytes = ctx->dc_bios->integrated_info->memory_type == 0x22 ? 8 : 4;
+ dcn42_bw_params.num_channels = ctx->dc_bios->integrated_info->ma_channel_number ? ctx->dc_bios->integrated_info->ma_channel_number : 1;
+ clk_mgr->base.base.dprefclk_khz = dcn42_smu_get_dprefclk(&clk_mgr->base);
+ clk_mgr->base.base.clks.ref_dtbclk_khz = dcn42_smu_get_dtbclk(&clk_mgr->base);
+
+ clk_mgr->base.base.bw_params = &dcn42_bw_params;
+
+ if (clk_mgr->base.smu_present)
+ dcn42_get_smu_clocks(&clk_mgr->base);
+ }
+ /* in case we don't get a value from the BIOS, use default */
+ if (clk_mgr->base.base.dentist_vco_freq_khz == 0)
+ clk_mgr->base.base.dentist_vco_freq_khz = 3000000; /* 3000MHz */
+
+ /* Saved clocks configured at boot for debug purposes */
+ dcn42_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, clk_mgr);
+
+ dce_clock_read_ss_info(&clk_mgr->base);
+ /*when clk src is from FCH, it could have ss, same clock src as DPREF clk*/
+
+ dcn42_read_ss_info_from_lut(&clk_mgr->base);
+
+ clk_mgr->base.base.bw_params = &dcn42_bw_params;
+ if (clk_mgr->base.smu_present)
+ dcn42_get_smu_clocks(&clk_mgr->base);
+}
+
+void dcn42_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int)
+{
+ struct clk_mgr_dcn42 *clk_mgr = TO_CLK_MGR_DCN42(clk_mgr_int);
+
+ if (clk_mgr->smu_wm_set.wm_set && clk_mgr->smu_wm_set.mc_address.quad_part != 0)
+ dm_helpers_free_gpu_mem(clk_mgr_int->base.ctx, DC_MEM_ALLOC_TYPE_GART,
+ clk_mgr->smu_wm_set.wm_set);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h
new file mode 100644
index 000000000000..9568ca06f00f
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_clk_mgr.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __DCN42_CLK_MGR_H__
+#define __DCN42_CLK_MGR_H__
+#include "clk_mgr_internal.h"
+
+#define NUM_CLOCK_SOURCES 5
+#define DCN42_CLKIP_REFCLK 48000
+
+struct dcn42_watermarks;
+
+struct dcn42_smu_watermark_set {
+ struct dcn42_watermarks *wm_set;
+ union large_integer mc_address;
+};
+
+struct dcn42_ss_info_table {
+ uint32_t ss_divider;
+ uint32_t ss_percentage[NUM_CLOCK_SOURCES];
+};
+
+struct clk_mgr_dcn42 {
+ struct clk_mgr_internal base;
+ struct dcn42_smu_watermark_set smu_wm_set;
+};
+
+bool dcn42_are_clock_states_equal(struct dc_clocks *a,
+ struct dc_clocks *b);
+void dcn42_init_clocks(struct clk_mgr *clk_mgr);
+void dcn42_update_clocks(struct clk_mgr *clk_mgr_base,
+ struct dc_state *context,
+ bool safe_to_lower);
+
+void dcn42_clk_mgr_construct(struct dc_context *ctx,
+ struct clk_mgr_dcn42 *clk_mgr,
+ struct pp_smu_funcs *pp_smu,
+ struct dccg *dccg);
+
+void dcn42_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr_int);
+
+void dcn42_init_single_clock(unsigned int *entry_0,
+ uint32_t *smu_entry_0,
+ uint8_t num_levels);
+unsigned int dcn42_convert_wck_ratio(uint8_t wck_ratio);
+extern struct dcn42_ss_info_table dcn42_ss_info_table;
+void dcn42_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn42_watermarks *table);
+void dcn42_enable_pme_wa(struct clk_mgr *clk_mgr_base);
+void dcn42_notify_wm_ranges(struct clk_mgr *clk_mgr_base);
+void dcn42_set_low_power_state(struct clk_mgr *clk_mgr_base);
+void dcn42_exit_low_power_state(struct clk_mgr *clk_mgr_base);
+unsigned int dcn42_get_max_clock_khz(struct clk_mgr *clk_mgr_base, enum clk_type clk_type);
+bool dcn42_is_smu_present(struct clk_mgr *clk_mgr_base);
+bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context);
+int dcn42_get_active_display_cnt_wa(struct dc *dc, struct dc_state *context, int *all_active_disps);
+bool dcn42_has_active_display(struct dc *dc, const struct dc_state *context);
+void dcn42_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, bool safe_to_lower);
+void dcn42_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr, struct dc_state *context, int ref_dtbclk_khz);
+bool dcn42_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base);
+struct dcn42_smu_dpm_clks; /* Forward declaration for pointer parameter below */
+void dcn42_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr, struct dcn42_smu_dpm_clks *smu_dpm_clks);
+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);
+#endif //__DCN42_CLK_MGR_H__
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.c
new file mode 100644
index 000000000000..c791bb1edb47
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.c
@@ -0,0 +1,431 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+
+
+#include "core_types.h"
+#include "clk_mgr_internal.h"
+#include "reg_helper.h"
+#include "dm_helpers.h"
+#include "dcn42_smu.h"
+
+#include "mp/mp_15_0_0_offset.h"
+#include "mp/mp_15_0_0_sh_mask.h"
+
+#ifdef BASE_INNER
+#undef BASE_INNER
+#endif
+
+#define MP1_BASE__INST0_SEG0 0x00016000
+#define MP1_BASE__INST0_SEG1 0x00016200
+#define MP1_BASE__INST0_SEG2 0x00E00000
+#define MP1_BASE__INST0_SEG3 0x00E80000
+#define MP1_BASE__INST0_SEG4 0x00EC0000
+#define MP1_BASE__INST0_SEG5 0x00F00000
+#define MP1_BASE__INST0_SEG6 0x02400400
+#define MP1_BASE__INST0_SEG7 0x0243F400
+#define MP1_BASE__INST0_SEG8 0x3C004000
+#define MP1_BASE__INST0_SEG9 0x3C3F4000
+
+#define BASE_INNER(seg) MP1_BASE__INST0_SEG ## seg
+
+#define BASE(seg) BASE_INNER(seg)
+
+#define REG(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name)
+
+#define FN(reg_name, field) \
+ FD(reg_name##__##field)
+
+#include "logger_types.h"
+#undef DC_LOGGER
+#define DC_LOGGER \
+ CTX->logger
+#define smu_print(str, ...) {DC_LOG_SMU(str, ##__VA_ARGS__); }
+
+// VBIOS and DAL to PMFW Interface
+
+// DAL to PMFW interface registers
+#define DAL_MSG_REG MP1_SMN_C2PMSG_71
+#define DAL_RESP_REG MP1_SMN_C2PMSG_72
+#define DAL_ARG_REG MP1_SMN_C2PMSG_73
+
+/** @defgroup ResponseCodes PMFW Response Codes
+* @{
+*/
+// SMU Response Codes:
+#define DALSMC_Result_OK 0x01 ///< Message Response OK
+#define DALSMC_Result_Failed 0xFF ///< Message Response Failed
+#define DALSMC_Result_UnknownCmd 0xFE ///< Message Response Unknown Command
+#define DALSMC_Result_CmdRejectedPrereq 0xFD ///< Message Response Command Failed Prerequisite
+#define DALSMC_Result_CmdRejectedBusy 0xFC ///< Message Response Command Rejected due to PMFW is busy. Sender should retry sending this message
+/** @}*/
+
+// Message Definitions:
+/** @defgroup definitions Message definitions
+* @{
+*/
+#define DALSMC_MSG_TestMessage 0x01 ///< To check if PMFW is alive and responding. Requirement specified by PMFW team
+#define DALSMC_MSG_GetPmfwVersion 0x02 ///< Get version
+#define DALSMC_MSG_SetDispclkFreq 0x03 ///< Set display clock frequency in MHZ
+#define DALSMC_MSG_SetDppclkFreq 0x04 ///< Set DPP clock frequency in MHZ
+#define DALSMC_MSG_SetHardMinDcfclkByFreq 0x05 ///< Set DCF clock frequency hard min in MHZ
+#define DALSMC_MSG_SetMinDeepSleepDcfclk 0x06 ///< Set DCF clock minimum frequency in deep sleep in MHZ
+#define DALSMC_MSG_UpdatePmeRestore 0x07 ///< To ask PMFW to write into Azalia for PME wake up event
+#define DALSMC_MSG_SetDramAddrHigh 0x08 ///< Set DRAM address high 32 bits for WM table transfer
+#define DALSMC_MSG_SetDramAddrLow 0x09 ///< Set DRAM address low 32 bits for WM table transfer
+
+#define DALSMC_MSG_TransferTableSmu2Dram 0x0A ///< Transfer table from PMFW SRAM to system DRAM
+#define DALSMC_MSG_TransferTableDram2Smu 0x0B ///< Transfer table from system DRAM to PMFW
+#define DALSMC_MSG_SetDisplayIdleOptimizations 0x0C ///< Set Idle state optimization for display off
+#define DALSMC_MSG_GetDprefclkFreq 0x0D ///< Get DPREF clock frequency. Return in MHZ
+#define DALSMC_MSG_GetDtbclkFreq 0x0E ///< Get DTB clock frequency. Return in MHZ
+#define DALSMC_MSG_AllowZstatesEntry 0x0F ///< Inform PMFW of display allowing Zstate entry
+#define DALSMC_MSG_SetDtbClk 0x10 ///< Inform PMFW to turn of/off DTB cl0ck. arg = 1: turn DTB on with 600MHZ; arg = 0: turn DTB clk off
+#define DALSMC_MSG_DispIPS2Exit 0x11 ///< Display IPS2 exit
+
+#define DALSMC_MSG_QueryIPS2Support 0x12 ///< Return 1: support; else not supported
+#define DALSMC_Message_Count 0x13 ///< Total number of VBIS and DAL messages
+/** @}*/
+
+
+union dcn42_dpia_host_router_bw {
+ struct {
+ uint32_t hr_id : 16;
+ uint32_t bw_mbps : 16;
+ } bits;
+ uint32_t all;
+};
+
+/*
+ * Function to be used instead of REG_WAIT macro because the wait ends when
+ * the register is NOT EQUAL to zero, and because `the translation in msg_if.h
+ * won't work with REG_WAIT.
+ */
+static uint32_t dcn42_smu_wait_for_response(struct clk_mgr_internal *clk_mgr,
+ unsigned int delay_us, unsigned int max_retries)
+{
+ uint32_t res_val;
+
+ do {
+ res_val = REG_READ(DAL_RESP_REG);
+ if (res_val != DALSMC_Result_CmdRejectedBusy)
+ break;
+
+ if (delay_us >= 1000)
+ msleep(delay_us/1000);
+ else if (delay_us > 0)
+ udelay(delay_us);
+
+ if (clk_mgr->base.ctx->dc->debug.disable_timeout)
+ max_retries++;
+ } while (max_retries--);
+
+ return res_val;
+}
+
+static int dcn42_smu_send_msg_with_param(struct clk_mgr_internal *clk_mgr,
+ unsigned int msg_id,
+ unsigned int param)
+{
+ uint32_t result;
+
+ result = dcn42_smu_wait_for_response(clk_mgr, 10, 2000000);
+
+ if (result != DALSMC_Result_OK) {
+ DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id);
+
+ if (result == DALSMC_Result_CmdRejectedBusy)
+ return -1;
+ }
+
+ /* First clear response register */
+ REG_WRITE(DAL_RESP_REG, DALSMC_Result_CmdRejectedBusy);
+
+ /* Set the parameter register for the SMU message, unit is Mhz */
+ REG_WRITE(DAL_ARG_REG, param);
+
+ /* Trigger the message transaction by writing the message ID */
+ REG_WRITE(DAL_MSG_REG, msg_id);
+
+ result = dcn42_smu_wait_for_response(clk_mgr, 10, 2000000);
+
+ if (result == DALSMC_Result_Failed) {
+ if (msg_id == DALSMC_MSG_TransferTableDram2Smu &&
+ param == TABLE_WATERMARKS)
+ DC_LOG_WARNING("Watermarks table not configured properly by SMU");
+ REG_WRITE(DAL_RESP_REG, DALSMC_Result_OK);
+ DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id);
+ return -1;
+ }
+
+ if (IS_SMU_TIMEOUT(result)) {
+ ASSERT(0);
+ result = dcn42_smu_wait_for_response(clk_mgr, 10, 2000000);
+ //dm_helpers_smu_timeout(CTX, msg_id, param, 10 * 200000);
+ DC_LOG_WARNING("SMU response after wait: %d, msg id = %d\n", result, msg_id);
+ }
+
+ return REG_READ(DAL_ARG_REG);
+}
+
+int dcn42_smu_get_pmfw_version(struct clk_mgr_internal *clk_mgr)
+{
+ return dcn42_smu_send_msg_with_param(
+ clk_mgr,
+ DALSMC_MSG_GetPmfwVersion,
+ 0);
+}
+
+
+int dcn42_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz)
+{
+ int actual_dispclk_set_mhz;
+
+ if (!clk_mgr->smu_present)
+ return requested_dispclk_khz;
+
+ /* Unit of SMU msg parameter is Mhz */
+ actual_dispclk_set_mhz = dcn42_smu_send_msg_with_param(
+ clk_mgr,
+ DALSMC_MSG_SetDispclkFreq,
+ khz_to_mhz_ceil(requested_dispclk_khz));
+
+ smu_print("requested_dispclk_khz = %d, actual_dispclk_set_mhz: %d\n",
+ requested_dispclk_khz, actual_dispclk_set_mhz);
+ return (int)((long long)actual_dispclk_set_mhz * 1000);
+}
+
+
+int dcn42_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz)
+{
+ int actual_dcfclk_set_mhz;
+
+ if (!clk_mgr->smu_present)
+ return requested_dcfclk_khz;
+
+ actual_dcfclk_set_mhz = dcn42_smu_send_msg_with_param(
+ clk_mgr,
+ DALSMC_MSG_SetHardMinDcfclkByFreq,
+ khz_to_mhz_ceil(requested_dcfclk_khz));
+
+ smu_print("requested_dcfclk_khz = %d, actual_dcfclk_set_mhz: %d\n",
+ requested_dcfclk_khz, actual_dcfclk_set_mhz);
+
+ return (int)((long long)actual_dcfclk_set_mhz * 1000);
+}
+
+int dcn42_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz)
+{
+ int actual_min_ds_dcfclk_mhz;
+
+ if (!clk_mgr->smu_present)
+ return requested_min_ds_dcfclk_khz;
+
+ actual_min_ds_dcfclk_mhz = dcn42_smu_send_msg_with_param(
+ clk_mgr,
+ DALSMC_MSG_SetMinDeepSleepDcfclk,
+ khz_to_mhz_ceil(requested_min_ds_dcfclk_khz));
+
+ smu_print("requested_min_ds_dcfclk_khz = %d, actual_min_ds_dcfclk_mhz: %d\n",
+ requested_min_ds_dcfclk_khz, actual_min_ds_dcfclk_mhz);
+
+ return (int)((long long)actual_min_ds_dcfclk_mhz * 1000);
+}
+
+int dcn42_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz)
+{
+ int actual_dppclk_set_mhz;
+
+ if (!clk_mgr->smu_present)
+ return requested_dpp_khz;
+
+ actual_dppclk_set_mhz = dcn42_smu_send_msg_with_param(
+ clk_mgr,
+ DALSMC_MSG_SetDppclkFreq,
+ khz_to_mhz_ceil(requested_dpp_khz));
+
+ smu_print("requested_dpp_khz = %d, actual_dppclk_set_mhz: %d\n",
+ requested_dpp_khz, actual_dppclk_set_mhz);
+
+ return (int)((long long)actual_dppclk_set_mhz * 1000);
+}
+
+void dcn42_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info)
+{
+ if (!clk_mgr->base.ctx->dc->debug.pstate_enabled)
+ return;
+
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn42_smu_send_msg_with_param(
+ clk_mgr,
+ DALSMC_MSG_SetDisplayIdleOptimizations,
+ idle_info);
+ smu_print("%s: SMC_MSG_SetDisplayIdleOptimizations idle_info = %x\n", __func__, idle_info);
+}
+
+void dcn42_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable)
+{
+ union display_idle_optimization_u idle_info = { 0 };
+
+ if (!clk_mgr->smu_present)
+ return;
+
+ if (enable) {
+ idle_info.idle_info.df_request_disabled = 1;
+ idle_info.idle_info.phy_ref_clk_off = 1;
+ }
+
+ dcn42_smu_send_msg_with_param(
+ clk_mgr,
+ DALSMC_MSG_SetDisplayIdleOptimizations,
+ idle_info.data);
+ smu_print("%s smu_enable_phy_refclk_pwrdwn = %d\n", __func__, enable ? 1 : 0);
+}
+
+void dcn42_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr)
+{
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn42_smu_send_msg_with_param(
+ clk_mgr,
+ DALSMC_MSG_UpdatePmeRestore,
+ 0);
+ smu_print("%s: SMC_MSG_UpdatePmeRestore\n", __func__);
+}
+
+void dcn42_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high)
+{
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn42_smu_send_msg_with_param(clk_mgr,
+ DALSMC_MSG_SetDramAddrHigh, addr_high);
+}
+
+void dcn42_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low)
+{
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn42_smu_send_msg_with_param(clk_mgr,
+ DALSMC_MSG_SetDramAddrLow, addr_low);
+}
+
+void dcn42_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr)
+{
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn42_smu_send_msg_with_param(clk_mgr,
+ DALSMC_MSG_TransferTableSmu2Dram, TABLE_DPMCLOCKS);
+}
+
+void dcn42_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr)
+{
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn42_smu_send_msg_with_param(clk_mgr,
+ DALSMC_MSG_TransferTableDram2Smu, TABLE_WATERMARKS);
+}
+
+void dcn42_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support)
+{
+ unsigned int msg_id, param, retv;
+
+ if (!clk_mgr->smu_present)
+ return;
+
+ switch (support) {
+
+ case DCN_ZSTATE_SUPPORT_ALLOW:
+ msg_id = DALSMC_MSG_AllowZstatesEntry;
+ param = (1 << 10) | (1 << 9) | (1 << 8);
+ smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW, param = 0x%x\n", __func__, param);
+ break;
+
+ case DCN_ZSTATE_SUPPORT_DISALLOW:
+ msg_id = DALSMC_MSG_AllowZstatesEntry;
+ param = 0;
+ smu_print("%s: SMC_MSG_AllowZstatesEntry msg_id = DISALLOW, param = 0x%x\n", __func__, param);
+ break;
+
+
+ case DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY:
+ msg_id = DALSMC_MSG_AllowZstatesEntry;
+ param = (1 << 10);
+ smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z10_ONLY, param = 0x%x\n", __func__, param);
+ break;
+
+ case DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY:
+ msg_id = DALSMC_MSG_AllowZstatesEntry;
+ param = (1 << 10) | (1 << 8);
+ smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z8_Z10_ONLY, param = 0x%x\n", __func__, param);
+ break;
+
+ case DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY:
+ msg_id = DALSMC_MSG_AllowZstatesEntry;
+ param = (1 << 8);
+ smu_print("%s: SMC_MSG_AllowZstatesEntry msg = ALLOW_Z8_ONLY, param = 0x%x\n", __func__, param);
+ break;
+
+ default: //DCN_ZSTATE_SUPPORT_UNKNOWN
+ msg_id = DALSMC_MSG_AllowZstatesEntry;
+ param = 0;
+ break;
+ }
+
+
+ retv = dcn42_smu_send_msg_with_param(
+ clk_mgr,
+ msg_id,
+ param);
+ smu_print("%s: msg_id = %d, param = 0x%x, return = 0x%x\n", __func__, msg_id, param, retv);
+}
+
+int dcn42_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr)
+{
+ int dprefclk;
+
+ if (!clk_mgr->smu_present)
+ return 0;
+
+ dprefclk = dcn42_smu_send_msg_with_param(clk_mgr,
+ DALSMC_MSG_GetDprefclkFreq,
+ 0);
+
+ smu_print("%s: SMU DPREF clk = %d mhz\n", __func__, dprefclk);
+ return (int)((long long)dprefclk * 1000);
+}
+
+int dcn42_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr)
+{
+ int dtbclk;
+
+ if (!clk_mgr->smu_present)
+ return 0;
+
+ dtbclk = dcn42_smu_send_msg_with_param(clk_mgr,
+ DALSMC_MSG_GetDtbclkFreq,
+ 0);
+
+ smu_print("%s: get_dtbclk = %dmhz\n", __func__, dtbclk);
+ return (int)((long long)dtbclk * 1000);
+}
+/* Arg = 1: Turn DTB on; 0: Turn DTB CLK OFF. when it is on, it is 600MHZ */
+void dcn42_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable)
+{
+ if (!clk_mgr->smu_present)
+ return;
+
+ dcn42_smu_send_msg_with_param(
+ clk_mgr,
+ DALSMC_MSG_SetDtbClk,
+ enable);
+ smu_print("%s: smu_set_dtbclk = %d\n", __func__, enable ? 1 : 0);
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.h
new file mode 100644
index 000000000000..8ba7ff04dc05
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn42/dcn42_smu.h
@@ -0,0 +1,190 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef DAL_DC_42_SMU_H_
+#define DAL_DC_42_SMU_H_
+
+#include "os_types.h"
+
+#ifndef PMFW_DRIVER_IF_H
+#define PMFW_DRIVER_IF_H
+#define PMFW_DRIVER_IF_VERSION 7
+
+typedef enum {
+ DSPCLK_DCFCLK = 0,
+ DSPCLK_DISPCLK,
+ DSPCLK_PIXCLK,
+ DSPCLK_PHYCLK,
+ DSPCLK_COUNT,
+} DSPCLK_e;
+
+typedef struct {
+ uint16_t Freq; // in MHz
+ uint16_t Vid; // min voltage in SVI3 VID
+} DisplayClockTable_t;
+
+typedef struct {
+ uint16_t MinClock; // This is either DCFCLK or SOCCLK (in MHz)
+ uint16_t MaxClock; // This is either DCFCLK or SOCCLK (in MHz)
+ uint16_t MinMclk;
+ uint16_t MaxMclk;
+
+ uint8_t WmSetting;
+ uint8_t WmType; // Used for normal pstate change or memory retraining
+ uint8_t Padding[2];
+} WatermarkRowGeneric_t;
+
+#define NUM_WM_RANGES 4
+#define WM_PSTATE_CHG 0
+#define WM_RETRAINING 1
+
+typedef enum {
+ WM_SOCCLK = 0,
+ WM_DCFCLK,
+ WM_COUNT,
+} WM_CLOCK_e;
+
+typedef struct {
+ WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES];
+
+ uint32_t MmHubPadding[7]; // SMU internal use
+} Watermarks_t;
+
+#define NUM_DCFCLK_DPM_LEVELS 8
+#define NUM_DISPCLK_DPM_LEVELS 8
+#define NUM_DPPCLK_DPM_LEVELS 8
+#define NUM_SOCCLK_DPM_LEVELS 8
+#define NUM_VCN_DPM_LEVELS 8
+#define NUM_SOC_VOLTAGE_LEVELS 8
+#define NUM_VPE_DPM_LEVELS 8
+#define NUM_FCLK_DPM_LEVELS 8
+#define NUM_MEM_PSTATE_LEVELS 4
+
+typedef enum {
+ WCK_RATIO_1_1 = 0, // DDR5, Wck:ck is always 1:1;
+ WCK_RATIO_1_2,
+ WCK_RATIO_1_4,
+ WCK_RATIO_MAX
+} WCK_RATIO_e;
+
+typedef struct {
+ uint32_t UClk;
+ uint32_t MemClk;
+ uint32_t Voltage;
+ uint8_t WckRatio;
+ uint8_t Spare[3];
+} MemPstateTable_t;
+
+
+ // Watermarks
+
+
+// Freq in MHz
+// Voltage in milli volts with 2 fractional bits
+typedef struct {
+ uint32_t DcfClocks[NUM_DCFCLK_DPM_LEVELS];
+ uint32_t DispClocks[NUM_DISPCLK_DPM_LEVELS];
+ uint32_t DppClocks[NUM_DPPCLK_DPM_LEVELS];
+ uint32_t SocClocks[NUM_SOCCLK_DPM_LEVELS];
+ uint32_t VClocks[NUM_VCN_DPM_LEVELS];
+ uint32_t DClocks[NUM_VCN_DPM_LEVELS];
+ uint32_t VPEClocks[NUM_VPE_DPM_LEVELS];
+ uint32_t FclkClocks_Freq[NUM_FCLK_DPM_LEVELS];
+ uint32_t FclkClocks_Voltage[NUM_FCLK_DPM_LEVELS];
+ uint32_t SocVoltage[NUM_SOC_VOLTAGE_LEVELS];
+ MemPstateTable_t MemPstateTable[NUM_MEM_PSTATE_LEVELS];
+
+ uint8_t NumDcfClkLevelsEnabled;
+ uint8_t NumDispClkLevelsEnabled; //Applies to both Dispclk and Dppclk
+ uint8_t NumSocClkLevelsEnabled;
+ uint8_t VcnClkLevelsEnabled; //Applies to both Vclk and Dclk
+
+ uint8_t VpeClkLevelsEnabled;
+ uint8_t NumMemPstatesEnabled;
+ uint8_t NumFclkLevelsEnabled;
+ uint8_t spare;
+
+ uint32_t MinGfxClk;
+ uint32_t MaxGfxClk;
+} DpmClocks_t_dcn42;
+
+// Throttler Status Bitmask
+
+
+#define TABLE_BIOS_IF 0 // Called by BIOS
+#define TABLE_WATERMARKS 1 // Called by DAL through VBIOS
+#define TABLE_CUSTOM_DPM 2 // Called by Driver
+#define TABLE_SPARE1 3
+#define TABLE_DPMCLOCKS 4 // Called by Driver
+#define TABLE_MOMENTARY_PM 5 // Called by Tools
+#define TABLE_MODERN_STDBY 6 // Called by Tools for Modern Standby Log
+#define TABLE_SMU_METRICS 7 // Called by Driver
+#define TABLE_COUNT 8
+
+#endif
+
+struct dcn42_watermarks {
+ // Watermarks
+ WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES];
+ uint32_t MmHubPadding[7]; // SMU internal use
+};
+
+struct dcn42_smu_dpm_clks {
+ DpmClocks_t_dcn42 *dpm_clks;
+ union large_integer mc_address;
+};
+
+struct display_idle_optimization {
+ unsigned int df_request_disabled : 1;
+ unsigned int phy_ref_clk_off : 1;
+ unsigned int s0i2_rdy : 1;
+ unsigned int reserved : 29;
+};
+
+union display_idle_optimization_u {
+ struct display_idle_optimization idle_info;
+ uint32_t data;
+};
+
+int dcn42_smu_get_pmfw_version(struct clk_mgr_internal *clk_mgr);
+int dcn42_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz);
+int dcn42_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_dcfclk_khz);
+int dcn42_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz);
+int dcn42_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz);
+void dcn42_smu_set_display_idle_optimization(struct clk_mgr_internal *clk_mgr, uint32_t idle_info);
+void dcn42_smu_enable_phy_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable);
+void dcn42_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr);
+void dcn42_smu_set_dram_addr_high(struct clk_mgr_internal *clk_mgr, uint32_t addr_high);
+void dcn42_smu_set_dram_addr_low(struct clk_mgr_internal *clk_mgr, uint32_t addr_low);
+void dcn42_smu_transfer_dpm_table_smu_2_dram(struct clk_mgr_internal *clk_mgr);
+void dcn42_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr);
+
+void dcn42_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zstate_support_state support);
+void dcn42_smu_set_dtbclk(struct clk_mgr_internal *clk_mgr, bool enable);
+void dcn42_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable);
+
+int dcn42_smu_get_dtbclk(struct clk_mgr_internal *clk_mgr);
+int dcn42_smu_get_dprefclk(struct clk_mgr_internal *clk_mgr);
+
+#endif /* DAL_DC_42_SMU_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 3e87b6a553be..419f894c87b0 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -443,75 +443,6 @@ static bool set_long_vtotal(struct dc *dc, struct dc_stream_state *stream, struc
}
/**
- * dc_stream_adjust_vmin_vmax - look up pipe context & update parts of DRR
- * @dc: dc reference
- * @stream: Initial dc stream state
- * @adjust: Updated parameters for vertical_total_min and vertical_total_max
- *
- * Looks up the pipe context of dc_stream_state and updates the
- * vertical_total_min and vertical_total_max of the DRR, Dynamic Refresh
- * Rate, which is a power-saving feature that targets reducing panel
- * refresh rate while the screen is static
- *
- * Return: %true if the pipe context is found and adjusted;
- * %false if the pipe context is not found.
- */
-bool dc_stream_adjust_vmin_vmax(struct dc *dc,
- struct dc_stream_state *stream,
- struct dc_crtc_timing_adjust *adjust)
-{
- int i;
-
- /*
- * Don't adjust DRR while there's bandwidth optimizations pending to
- * avoid conflicting with firmware updates.
- */
- if (dc->ctx->dce_version > DCE_VERSION_MAX) {
- if (dc->optimized_required &&
- (stream->adjust.v_total_max != adjust->v_total_max ||
- stream->adjust.v_total_min != adjust->v_total_min)) {
- stream->adjust.timing_adjust_pending = true;
- return false;
- }
- }
-
- dc_exit_ips_for_hw_access(dc);
-
- stream->adjust.v_total_max = adjust->v_total_max;
- stream->adjust.v_total_mid = adjust->v_total_mid;
- stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num;
- stream->adjust.v_total_min = adjust->v_total_min;
- stream->adjust.allow_otg_v_count_halt = adjust->allow_otg_v_count_halt;
-
- if (dc->caps.max_v_total != 0 &&
- (adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) {
- stream->adjust.timing_adjust_pending = false;
- if (adjust->allow_otg_v_count_halt)
- return set_long_vtotal(dc, stream, adjust);
- else
- return false;
- }
-
- for (i = 0; i < MAX_PIPES; i++) {
- struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
-
- if (pipe->stream == stream && pipe->stream_res.tg) {
- dc->hwss.set_drr(&pipe,
- 1,
- *adjust);
- stream->adjust.timing_adjust_pending = false;
-
- if (dc->hwss.notify_cursor_offload_drr_update)
- dc->hwss.notify_cursor_offload_drr_update(dc, dc->current_state, stream);
-
- return true;
- }
- }
-
- return false;
-}
-
-/**
* dc_stream_get_last_used_drr_vtotal - Looks up the pipe context of
* dc_stream_state and gets the last VTOTAL used by DRR (Dynamic Refresh Rate)
*
@@ -1165,11 +1096,8 @@ static bool dc_construct(struct dc *dc,
#ifdef CONFIG_DRM_AMD_DC_FP
dc->clk_mgr->force_smu_not_present = init_params->force_smu_not_present;
- if (dc->res_pool->funcs->update_bw_bounding_box) {
- DC_FP_START();
+ if (dc->res_pool->funcs->update_bw_bounding_box)
dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
- DC_FP_END();
- }
dc->soc_and_ip_translator = dc_create_soc_and_ip_translator(dc_ctx->dce_version);
if (!dc->soc_and_ip_translator)
goto fail;
@@ -1206,6 +1134,8 @@ static void disable_all_writeback_pipes_for_stream(
struct dc_stream_state *stream,
struct dc_state *context)
{
+ (void)dc;
+ (void)context;
int i;
for (i = 0; i < stream->num_wb_info; i++)
@@ -1217,6 +1147,8 @@ static void apply_ctx_interdependent_lock(struct dc *dc,
struct dc_stream_state *stream,
bool lock)
{
+ (void)dc;
+ (void)context;
int i;
/* Checks if interdependent update function pointer is NULL or not, takes care of DCE110 case */
@@ -1274,6 +1206,8 @@ static void dc_update_visual_confirm_color(struct dc *dc, struct dc_state *conte
get_fams2_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color));
else if (dc->debug.visual_confirm == VISUAL_CONFIRM_VABC)
get_vabc_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
+ else if (dc->debug.visual_confirm == VISUAL_CONFIRM_BOOSTED_REFRESH_RATE)
+ get_refresh_rate_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
}
}
}
@@ -1323,6 +1257,83 @@ void dc_get_visual_confirm_for_stream(
}
}
+/**
+ * dc_stream_adjust_vmin_vmax - look up pipe context & update parts of DRR
+ * @dc: dc reference
+ * @stream: Initial dc stream state
+ * @adjust: Updated parameters for vertical_total_min and vertical_total_max
+ *
+ * Looks up the pipe context of dc_stream_state and updates the
+ * vertical_total_min and vertical_total_max of the DRR, Dynamic Refresh
+ * Rate, which is a power-saving feature that targets reducing panel
+ * refresh rate while the screen is static
+ *
+ * Return: %true if the pipe context is found and adjusted;
+ * %false if the pipe context is not found.
+ */
+bool dc_stream_adjust_vmin_vmax(struct dc *dc,
+ struct dc_stream_state *stream,
+ struct dc_crtc_timing_adjust *adjust)
+{
+ int i;
+
+ /*
+ * Don't adjust DRR while there's bandwidth optimizations pending to
+ * avoid conflicting with firmware updates.
+ */
+ if (dc->ctx->dce_version > DCE_VERSION_MAX) {
+ if (dc->optimized_required &&
+ (stream->adjust.v_total_max != adjust->v_total_max ||
+ stream->adjust.v_total_min != adjust->v_total_min)) {
+ stream->adjust.timing_adjust_pending = true;
+ return false;
+ }
+ }
+
+ dc_exit_ips_for_hw_access(dc);
+
+ stream->adjust.v_total_max = adjust->v_total_max;
+ stream->adjust.v_total_mid = adjust->v_total_mid;
+ stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num;
+ stream->adjust.v_total_min = adjust->v_total_min;
+ stream->adjust.allow_otg_v_count_halt = adjust->allow_otg_v_count_halt;
+
+ if (dc->caps.max_v_total != 0 &&
+ (adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) {
+ stream->adjust.timing_adjust_pending = false;
+ if (adjust->allow_otg_v_count_halt)
+ return set_long_vtotal(dc, stream, adjust);
+ else
+ return false;
+ }
+
+ for (i = 0; i < MAX_PIPES; i++) {
+ struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (pipe->stream == stream && pipe->stream_res.tg) {
+ dc->hwss.set_drr(&pipe,
+ 1,
+ *adjust);
+ stream->adjust.timing_adjust_pending = false;
+
+ if (dc->debug.visual_confirm == VISUAL_CONFIRM_BOOSTED_REFRESH_RATE) {
+ if (pipe->stream && pipe->plane_state) {
+ dc_update_visual_confirm_color(dc, dc->current_state, pipe);
+ dc->hwss.update_visual_confirm_color(dc, pipe, pipe->plane_res.hubp->mpcc_id);
+
+ }
+ }
+
+ if (dc->hwss.notify_cursor_offload_drr_update)
+ dc->hwss.notify_cursor_offload_drr_update(dc, dc->current_state, stream);
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
{
int i, j;
@@ -1553,8 +1564,7 @@ static void detect_edp_presence(struct dc *dc)
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link = NULL;
enum dc_connection_type type;
- int i;
- int edp_num;
+ unsigned int i, edp_num;
dc_get_edp_links(dc, edp_links, &edp_num);
if (!edp_num)
@@ -1913,10 +1923,77 @@ bool dc_validate_boot_timing(const struct dc *dc,
return false;
}
- /* block DSC for now, as VBIOS does not currently support DSC timings */
if (crtc_timing->flags.DSC) {
- DC_LOG_DEBUG("boot timing validation failed due to DSC\n");
- return false;
+ struct display_stream_compressor *dsc = NULL;
+ struct dcn_dsc_state dsc_state = {0};
+
+ /* Find DSC associated with this timing generator */
+ if (tg_inst < dc->res_pool->res_cap->num_dsc) {
+ dsc = dc->res_pool->dscs[tg_inst];
+ }
+
+ if (!dsc || !dsc->funcs->dsc_read_state) {
+ DC_LOG_DEBUG("boot timing validation failed due to no DSC resource or read function\n");
+ return false;
+ }
+
+ /* Read current DSC hardware state */
+ dsc->funcs->dsc_read_state(dsc, &dsc_state);
+
+ /* Check if DSC is actually enabled in hardware */
+ if (dsc_state.dsc_clock_en == 0) {
+ DC_LOG_DEBUG("boot timing validation failed due to DSC not enabled in hardware\n");
+ return false;
+ }
+
+ uint32_t num_slices_h = 0;
+ uint32_t num_slices_v = 0;
+
+ if (dsc_state.dsc_slice_width > 0) {
+ num_slices_h = (crtc_timing->h_addressable + dsc_state.dsc_slice_width - 1) / dsc_state.dsc_slice_width;
+ }
+
+ if (dsc_state.dsc_slice_height > 0) {
+ num_slices_v = (crtc_timing->v_addressable + dsc_state.dsc_slice_height - 1) / dsc_state.dsc_slice_height;
+ }
+
+ if (crtc_timing->dsc_cfg.num_slices_h != num_slices_h) {
+ DC_LOG_DEBUG("boot timing validation failed due to num_slices_h mismatch\n");
+ return false;
+ }
+
+ if (crtc_timing->dsc_cfg.num_slices_v != num_slices_v) {
+ DC_LOG_DEBUG("boot timing validation failed due to num_slices_v mismatch\n");
+ return false;
+ }
+
+ if (crtc_timing->dsc_cfg.bits_per_pixel != dsc_state.dsc_bits_per_pixel) {
+ DC_LOG_DEBUG("boot timing validation failed due to bits_per_pixel mismatch\n");
+ return false;
+ }
+
+ if (crtc_timing->dsc_cfg.block_pred_enable != dsc_state.dsc_block_pred_enable) {
+ DC_LOG_DEBUG("boot timing validation failed due to block_pred_enable mismatch\n");
+ return false;
+ }
+
+ if (crtc_timing->dsc_cfg.linebuf_depth != dsc_state.dsc_line_buf_depth) {
+ DC_LOG_DEBUG("boot timing validation failed due to linebuf_depth mismatch\n");
+ return false;
+ }
+
+ if (crtc_timing->dsc_cfg.version_minor != dsc_state.dsc_version_minor) {
+ DC_LOG_DEBUG("boot timing validation failed due to version_minor mismatch\n");
+ return false;
+ }
+
+ if (crtc_timing->dsc_cfg.ycbcr422_simple != dsc_state.dsc_simple_422) {
+ DC_LOG_DEBUG("boot timing validation failed due to pixel encoding mismatch\n");
+ return false;
+ }
+
+ // Skip checks for is_frl, is_dp, and rc_buffer_size which are not programmed by vbios
+ // or not necessary for seamless boot validation.
}
if (dc_is_dp_signal(link->connector_signal)) {
@@ -2607,6 +2684,16 @@ void dc_post_update_surfaces_to_stream(struct dc *dc)
dc->optimized_required = false;
}
+void dc_get_default_tiling_info(const struct dc *dc, struct dc_tiling_info *tiling_info)
+{
+ if (!dc || !tiling_info)
+ return;
+ if (dc->res_pool && dc->res_pool->funcs && dc->res_pool->funcs->get_default_tiling_info) {
+ dc->res_pool->funcs->get_default_tiling_info(tiling_info);
+ return;
+ }
+}
+
bool dc_set_generic_gpio_for_stereo(bool enable,
struct gpio_service *gpio_service)
{
@@ -2749,28 +2836,12 @@ static struct surface_update_descriptor get_plane_info_update_type(const struct
if (memcmp(tiling, &u->surface->tiling_info, sizeof(*tiling)) != 0) {
update_flags->bits.swizzle_change = 1;
- elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
- switch (tiling->gfxversion) {
- case DcGfxVersion9:
- case DcGfxVersion10:
- case DcGfxVersion11:
- if (tiling->gfx9.swizzle != DC_SW_LINEAR) {
- update_flags->bits.bandwidth_change = 1;
- elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
- }
- break;
- case DcGfxAddr3:
- if (tiling->gfx_addr3.swizzle != DC_ADDR3_SW_LINEAR) {
- update_flags->bits.bandwidth_change = 1;
- elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
- }
- break;
- case DcGfxVersion7:
- case DcGfxVersion8:
- case DcGfxVersionUnknown:
- default:
- break;
+ if (tiling->flags.avoid_full_update_on_tiling_change) {
+ elevate_update_type(&update_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM);
+ } else {
+ update_flags->bits.bandwidth_change = 1;
+ elevate_update_type(&update_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
}
@@ -2885,16 +2956,27 @@ static struct surface_update_descriptor det_surface_update(
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
}
- if (u->blend_tf || (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) {
+ if (u->cm || (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) {
update_flags->bits.gamma_change = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
}
- if (u->lut3d_func || u->func_shaper) {
+ if (u->cm && (u->cm->flags.bits.lut3d_enable || u->surface->cm.flags.bits.lut3d_enable)) {
update_flags->bits.lut_3d = 1;
elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
}
+ if (u->cm && u->cm->flags.bits.lut3d_dma_enable != u->surface->cm.flags.bits.lut3d_dma_enable &&
+ u->cm->flags.bits.lut3d_enable && u->surface->cm.flags.bits.lut3d_enable) {
+ /* Toggling 3DLUT loading between DMA and Host is illegal */
+ BREAK_TO_DEBUGGER();
+ }
+
+ if (u->cm && u->cm->flags.bits.lut3d_enable && !u->cm->flags.bits.lut3d_dma_enable) {
+ /* Host loading 3DLUT requires full update but only stream lock */
+ elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_STREAM);
+ }
+
if (u->hdr_mult.value)
if (u->hdr_mult.value != u->surface->hdr_mult.value) {
// TODO: Should be fast?
@@ -2909,24 +2991,15 @@ static struct surface_update_descriptor det_surface_update(
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
- if (u->cm2_params) {
- if (u->cm2_params->component_settings.shaper_3dlut_setting != u->surface->mcm_shaper_3dlut_setting
- || u->cm2_params->component_settings.lut1d_enable != u->surface->mcm_lut1d_enable
- || u->cm2_params->cm2_luts.lut3d_data.lut3d_src != u->surface->mcm_luts.lut3d_data.lut3d_src) {
- update_flags->bits.mcm_transfer_function_enable_change = 1;
- elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
- }
- }
-
- if (update_flags->bits.lut_3d &&
- u->surface->mcm_luts.lut3d_data.lut3d_src != DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
- elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
+ if (u->cm_hist_control) {
+ update_flags->bits.cm_hist_change = 1;
+ elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM);
}
-
if (check_config->enable_legacy_fast_update &&
(update_flags->bits.gamma_change ||
update_flags->bits.gamut_remap_change ||
update_flags->bits.input_csc_change ||
+ update_flags->bits.cm_hist_change ||
update_flags->bits.coeff_reduction_change)) {
elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL);
}
@@ -2938,6 +3011,7 @@ static struct surface_update_descriptor det_surface_update(
*/
static void force_immediate_gsl_plane_flip(struct dc *dc, struct dc_surface_update *updates, int surface_count)
{
+ (void)dc;
bool has_flip_immediate_plane = false;
int i;
@@ -3064,7 +3138,7 @@ struct surface_update_descriptor dc_check_update_surfaces_for_stream(
{
if (stream_update)
stream_update->stream->update_flags.raw = 0;
- for (size_t i = 0; i < surface_count; i++)
+ for (int i = 0; i < surface_count; i++)
updates[i].surface->update_flags.raw = 0;
return check_update_surfaces_for_stream(check_config, updates, surface_count, stream_update);
@@ -3158,6 +3232,11 @@ static void copy_surface_update_to_plane(
surface->gamma_correction.type =
srf_update->gamma->type;
}
+ if (srf_update->cm_hist_control) {
+ memcpy(&surface->cm_hist_control,
+ srf_update->cm_hist_control,
+ sizeof(surface->cm_hist_control));
+ }
if (srf_update->in_transfer_func) {
surface->in_transfer_func.sdr_ref_white_level =
@@ -3171,24 +3250,12 @@ static void copy_surface_update_to_plane(
sizeof(struct dc_transfer_func_distributed_points));
}
- if (srf_update->cm2_params) {
- surface->mcm_shaper_3dlut_setting = srf_update->cm2_params->component_settings.shaper_3dlut_setting;
- surface->mcm_lut1d_enable = srf_update->cm2_params->component_settings.lut1d_enable;
- surface->mcm_luts = srf_update->cm2_params->cm2_luts;
- }
-
- if (srf_update->func_shaper) {
- memcpy(&surface->in_shaper_func, srf_update->func_shaper,
- sizeof(surface->in_shaper_func));
-
- if (surface->mcm_shaper_3dlut_setting >= DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER)
- surface->mcm_luts.shaper = &surface->in_shaper_func;
+ /* Shaper, 3DLUT, 1DLUT */
+ if (srf_update->cm) {
+ memcpy(&surface->cm, srf_update->cm,
+ sizeof(surface->cm));
}
- if (srf_update->lut3d_func)
- memcpy(&surface->lut3d_func, srf_update->lut3d_func,
- sizeof(surface->lut3d_func));
-
if (srf_update->hdr_mult.value)
surface->hdr_mult =
srf_update->hdr_mult;
@@ -3197,17 +3264,6 @@ static void copy_surface_update_to_plane(
surface->sdr_white_level_nits =
srf_update->sdr_white_level_nits;
- if (srf_update->blend_tf) {
- memcpy(&surface->blend_tf, srf_update->blend_tf,
- sizeof(surface->blend_tf));
-
- if (surface->mcm_lut1d_enable)
- surface->mcm_luts.lut1d_func = &surface->blend_tf;
- }
-
- if (srf_update->cm2_params || srf_update->blend_tf)
- 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;
@@ -3234,6 +3290,7 @@ static void copy_stream_update_to_stream(struct dc *dc,
struct dc_stream_state *stream,
struct dc_stream_update *update)
{
+ (void)context;
struct dc_context *dc_ctx = dc->ctx;
if (update == NULL || stream == NULL)
@@ -3509,6 +3566,7 @@ static void restore_minimal_pipe_split_policy(struct dc *dc,
* @surface_count: surface update count
* @stream: Corresponding stream to be updated
* @stream_update: stream update
+ * @update_descriptor: describes what plane and stream changes to apply
* @new_update_type: [out] determined update type by the function
* @new_context: [out] new context allocated and validated if update type is
* FULL, reference to current context if update type is less than FULL.
@@ -3837,6 +3895,7 @@ static void commit_planes_do_stream_update(struct dc *dc,
static bool dc_dmub_should_send_dirty_rect_cmd(struct dc *dc, struct dc_stream_state *stream)
{
+ (void)dc;
if ((stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1
|| stream->link->psr_settings.psr_version == DC_PSR_VERSION_1)
&& stream->ctx->dce_version >= DCN_VERSION_3_1)
@@ -4491,11 +4550,9 @@ static void commit_planes_for_stream(struct dc *dc,
if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state))
continue;
- if (srf_updates[i].cm2_params &&
- srf_updates[i].cm2_params->cm2_luts.lut3d_data.lut3d_src ==
- DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM &&
- srf_updates[i].cm2_params->component_settings.shaper_3dlut_setting ==
- DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT &&
+ if (srf_updates[i].cm &&
+ 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);
@@ -4639,6 +4696,7 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
int surface_count,
bool *is_plane_addition)
{
+ (void)srf_updates;
struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream);
bool force_minimal_pipe_splitting = false;
@@ -5063,6 +5121,9 @@ void populate_fast_updates(struct dc_fast_update *fast_update,
fast_update[i].input_csc_color_matrix = srf_updates[i].input_csc_color_matrix;
fast_update[i].coeff_reduction_factor = srf_updates[i].coeff_reduction_factor;
fast_update[i].cursor_csc_color_matrix = srf_updates[i].cursor_csc_color_matrix;
+#if defined(CONFIG_DRM_AMD_DC_DCN4_2)
+ fast_update[i].cm_hist_control = srf_updates[i].cm_hist_control;
+#endif
}
}
@@ -5080,6 +5141,9 @@ static bool fast_updates_exist(const struct dc_fast_update *fast_update, int sur
fast_update[i].gamut_remap_matrix ||
fast_update[i].input_csc_color_matrix ||
fast_update[i].cursor_csc_color_matrix ||
+#if defined(CONFIG_DRM_AMD_DC_DCN4_2)
+ fast_update[i].cm_hist_control ||
+#endif
fast_update[i].coeff_reduction_factor)
return true;
}
@@ -5100,6 +5164,9 @@ bool fast_nonaddr_updates_exist(struct dc_fast_update *fast_update, int surface_
fast_update[i].gamma ||
fast_update[i].gamut_remap_matrix ||
fast_update[i].coeff_reduction_factor ||
+#if defined(CONFIG_DRM_AMD_DC_DCN4_2)
+ fast_update[i].cm_hist_control ||
+#endif
fast_update[i].cursor_csc_color_matrix)
return true;
}
@@ -5114,6 +5181,7 @@ static bool full_update_required_weak(
const struct dc_stream_update *stream_update,
const struct dc_stream_state *stream)
{
+ (void)stream_update;
const struct dc_state *context = dc->current_state;
if (srf_updates)
for (int i = 0; i < surface_count; i++)
@@ -5141,6 +5209,12 @@ static bool full_update_required(
const struct dc_stream_update *stream_update,
const struct dc_stream_state *stream)
{
+ const union dc_plane_cm_flags blend_only_flags = {
+ .bits = {
+ .blend_enable = 1,
+ }
+ };
+
if (full_update_required_weak(dc, srf_updates, surface_count, stream_update, stream))
return true;
@@ -5153,14 +5227,12 @@ static bool full_update_required(
(srf_updates[i].sdr_white_level_nits &&
srf_updates[i].sdr_white_level_nits != srf_updates->surface->sdr_white_level_nits) ||
srf_updates[i].in_transfer_func ||
- srf_updates[i].func_shaper ||
- srf_updates[i].lut3d_func ||
srf_updates[i].surface->force_full_update ||
(srf_updates[i].flip_addr &&
srf_updates[i].flip_addr->address.tmz_surface != srf_updates[i].surface->address.tmz_surface) ||
- (srf_updates[i].cm2_params &&
- (srf_updates[i].cm2_params->component_settings.shaper_3dlut_setting != srf_updates[i].surface->mcm_shaper_3dlut_setting ||
- srf_updates[i].cm2_params->component_settings.lut1d_enable != srf_updates[i].surface->mcm_lut1d_enable))))
+ (srf_updates[i].cm &&
+ ((srf_updates[i].cm->flags.all != blend_only_flags.all && srf_updates[i].cm->flags.all != 0) ||
+ (srf_updates[i].surface->cm.flags.all != blend_only_flags.all && srf_updates[i].surface->cm.flags.all != 0)))))
return true;
}
@@ -5479,6 +5551,7 @@ void dc_commit_updates_for_stream(struct dc *dc,
struct dc_stream_update *stream_update,
struct dc_state *state)
{
+ (void)state;
bool ret = false;
dc_exit_ips_for_hw_access(dc);
@@ -5540,6 +5613,9 @@ void dc_power_down_on_boot(struct dc *dc)
{
if (dc->ctx->dce_environment != DCE_ENV_VIRTUAL_HW &&
dc->hwss.power_down_on_boot) {
+ if (dc->current_state->stream_count > 0)
+ return;
+
if (dc->caps.ips_support)
dc_exit_ips_for_hw_access(dc);
dc->hwss.power_down_on_boot(dc);
@@ -5551,12 +5627,12 @@ void dc_set_power_state(struct dc *dc, enum dc_acpi_cm_power_state power_state)
if (!dc->current_state)
return;
+ dc_exit_ips_for_hw_access(dc);
+
switch (power_state) {
case DC_ACPI_CM_POWER_STATE_D0:
dc_state_construct(dc, dc->current_state);
- dc_exit_ips_for_hw_access(dc);
-
dc_z10_restore(dc);
dc_dmub_srv_notify_fw_dc_power_state(dc->ctx->dmub_srv, power_state);
@@ -5785,6 +5861,7 @@ void dc_lock_memory_clock_frequency(struct dc *dc)
static void blank_and_force_memclk(struct dc *dc, bool apply, unsigned int memclk_mhz)
{
+ (void)apply;
struct dc_state *context = dc->current_state;
struct hubp *hubp;
struct pipe_ctx *pipe;
@@ -5932,6 +6009,7 @@ bool dc_is_dmub_outbox_supported(struct dc *dc)
case AMDGPU_FAMILY_GC_11_0_1:
case AMDGPU_FAMILY_GC_11_5_0:
+ case AMDGPU_FAMILY_GC_11_5_4:
if (!dc->debug.dpia_debug.bits.disable_dpia)
return true;
break;
@@ -6328,8 +6406,7 @@ void dc_disable_accelerated_mode(struct dc *dc)
*/
void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable)
{
- int i;
- int edp_num;
+ unsigned int i, edp_num;
struct pipe_ctx *pipe = NULL;
struct dc_link *link = stream->sink->link;
struct dc_link *edp_links[MAX_NUM_EDP];
@@ -6383,8 +6460,7 @@ bool dc_abm_save_restore(
struct dc_stream_state *stream,
struct abm_save_restore *pData)
{
- int i;
- int edp_num;
+ unsigned int i, edp_num;
struct pipe_ctx *pipe = NULL;
struct dc_link *link = stream->sink->link;
struct dc_link *edp_links[MAX_NUM_EDP];
@@ -6460,6 +6536,7 @@ void dc_query_current_properties(struct dc *dc, struct dc_current_properties *pr
void dc_set_edp_power(const struct dc *dc, struct dc_link *edp_link,
bool powerOn)
{
+ (void)dc;
if (edp_link->connector_signal != SIGNAL_TYPE_EDP)
return;
@@ -6586,6 +6663,7 @@ void dc_get_underflow_debug_data_for_otg(struct dc *dc, int primary_otg_inst,
void dc_get_power_feature_status(struct dc *dc, int primary_otg_inst,
struct power_features *out_data)
{
+ (void)primary_otg_inst;
out_data->uclk_p_state = dc->current_state->clk_mgr->clks.p_state_change_support;
out_data->fams = dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching;
}
@@ -6884,7 +6962,7 @@ bool dc_capture_register_software_state(struct dc *dc, struct dc_register_softwa
struct dc_plane_state *plane_state = pipe_ctx->plane_state;
/* MPCC blending tree and mode control - capture actual blend configuration */
- state->mpc.mpcc_mode[i] = (plane_state->blend_tf.type != TF_TYPE_BYPASS) ? 1 : 0;
+ state->mpc.mpcc_mode[i] = (plane_state->cm.blend_func.type != TF_TYPE_BYPASS) ? 1 : 0;
state->mpc.mpcc_alpha_blend_mode[i] = plane_state->per_pixel_alpha ? 1 : 0;
state->mpc.mpcc_alpha_multiplied_mode[i] = plane_state->pre_multiplied_alpha ? 1 : 0;
state->mpc.mpcc_blnd_active_overlap_only[i] = 0; /* Default - no overlap restriction */
@@ -7282,6 +7360,23 @@ static bool update_planes_and_stream_prepare_v3(
ASSERT(scratch->flow == UPDATE_V3_FLOW_INVALID);
dc_exit_ips_for_hw_access(scratch->dc);
+ /* HWSS path determination needs to be done prior to updating the surface and stream states. */
+ struct dc_fast_update fast_update[MAX_SURFACES] = { 0 };
+
+ populate_fast_updates(fast_update,
+ scratch->surface_updates,
+ scratch->surface_count,
+ scratch->stream_update);
+
+ const bool is_hwss_fast_path_only =
+ fast_update_only(scratch->dc,
+ fast_update,
+ scratch->surface_updates,
+ scratch->surface_count,
+ scratch->stream_update,
+ scratch->stream) &&
+ !scratch->dc->check_config.enable_legacy_fast_update;
+
if (!update_planes_and_stream_state(
scratch->dc,
scratch->surface_updates,
@@ -7297,26 +7392,7 @@ static bool update_planes_and_stream_prepare_v3(
if (scratch->new_context == scratch->dc->current_state) {
ASSERT(scratch->update_type < UPDATE_TYPE_FULL);
- // TODO: Do we need this to be alive in execute?
- struct dc_fast_update fast_update[MAX_SURFACES] = { 0 };
-
- populate_fast_updates(
- fast_update,
- scratch->surface_updates,
- scratch->surface_count,
- scratch->stream_update
- );
- const bool fast = fast_update_only(
- scratch->dc,
- fast_update,
- scratch->surface_updates,
- scratch->surface_count,
- scratch->stream_update,
- scratch->stream
- )
- // TODO: Can this be used to skip `populate_fast_updates`?
- && !scratch->dc->check_config.enable_legacy_fast_update;
- scratch->flow = fast
+ scratch->flow = is_hwss_fast_path_only
? UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST
: UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL;
return true;
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 052d573408c3..db86e346307c 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Advanced Micro Devices, Inc.
+ * Copyright 2015-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -249,6 +249,7 @@ void color_space_to_black_color(
enum dc_color_space colorspace,
struct tg_color *black_color)
{
+ (void)dc;
switch (colorspace) {
case COLOR_SPACE_YCBCR601:
case COLOR_SPACE_YCBCR709:
@@ -846,6 +847,16 @@ void hwss_build_fast_sequence(struct dc *dc,
block_sequence[*num_steps].func = DPP_PROGRAM_BIAS_AND_SCALE;
(*num_steps)++;
}
+ if (current_mpc_pipe->plane_state->update_flags.bits.cm_hist_change) {
+ block_sequence[*num_steps].params.control_cm_hist_params.dpp
+ = current_mpc_pipe->plane_res.dpp;
+ block_sequence[*num_steps].params.control_cm_hist_params.cm_hist_control
+ = current_mpc_pipe->plane_state->cm_hist_control;
+ block_sequence[*num_steps].params.control_cm_hist_params.color_space
+ = current_mpc_pipe->plane_state->color_space;
+ block_sequence[*num_steps].func = DPP_PROGRAM_CM_HIST;
+ (*num_steps)++;
+ }
}
if (hws->funcs.set_output_transfer_func && current_mpc_pipe->stream->update_flags.bits.out_tf) {
block_sequence[*num_steps].params.set_output_transfer_func_params.dc = dc;
@@ -1029,6 +1040,9 @@ void hwss_execute_sequence(struct dc *dc,
case HUBP_PROGRAM_MCACHE_ID:
hwss_program_mcache_id_and_split_coordinate(params);
break;
+ case DPP_PROGRAM_CM_HIST:
+ hwss_program_cm_hist(params);
+ break;
case PROGRAM_CURSOR_UPDATE_NOW:
dc->hwss.program_cursor_offload_now(
params->program_cursor_update_now_params.dc,
@@ -2054,6 +2068,16 @@ void hwss_program_mcache_id_and_split_coordinate(union block_sequence_params *pa
}
+void hwss_program_cm_hist(union block_sequence_params *params)
+{
+ struct dpp *dpp = params->control_cm_hist_params.dpp;
+
+ if (dpp && dpp->funcs->dpp_cm_hist_control)
+ dpp->funcs->dpp_cm_hist_control(dpp,
+ params->control_cm_hist_params.cm_hist_control,
+ params->control_cm_hist_params.color_space);
+}
+
void get_surface_tile_visual_confirm_color(
struct pipe_ctx *pipe_ctx,
struct tg_color *color)
@@ -3370,6 +3394,20 @@ void hwss_add_opp_program_bit_depth_reduction(struct block_sequence_state *seq_s
}
}
+void hwss_add_dpp_program_cm_hist(struct block_sequence_state *seq_state,
+ struct dpp *dpp,
+ struct cm_hist_control cm_hist_control,
+ enum dc_color_space color_space)
+{
+ if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) {
+ seq_state->steps[*seq_state->num_steps].func = DPP_PROGRAM_CM_HIST;
+ seq_state->steps[*seq_state->num_steps].params.control_cm_hist_params.dpp = dpp;
+ seq_state->steps[*seq_state->num_steps].params.control_cm_hist_params.cm_hist_control = cm_hist_control;
+ seq_state->steps[*seq_state->num_steps].params.control_cm_hist_params.color_space = color_space;
+ (*seq_state->num_steps)++;
+ }
+}
+
void hwss_add_dc_ip_request_cntl(struct block_sequence_state *seq_state,
struct dc *dc,
bool enable)
@@ -4071,3 +4109,24 @@ void hwss_add_tg_get_frame_count(struct block_sequence_state *seq_state,
(*seq_state->num_steps)++;
}
}
+
+
+void get_refresh_rate_confirm_color(struct pipe_ctx *pipe_ctx, struct tg_color *color)
+{
+ uint32_t color_value = MAX_TG_COLOR_VALUE;
+ unsigned int refresh_rate = 0;
+ uint32_t scaling_factor = 0;
+ if (pipe_ctx && pipe_ctx->stream && color) {
+ refresh_rate = (pipe_ctx->stream->timing.pix_clk_100hz * 100) / (pipe_ctx->stream->adjust.v_total_max * pipe_ctx->stream->timing.h_total);
+
+ uint32_t min_refresh_rate = pipe_ctx->stream->timing.min_refresh_in_uhz / 1000000;
+ uint32_t max_refresh_rate = pipe_ctx->stream->timing.max_refresh_in_uhz / 1000000;
+
+ if (max_refresh_rate - min_refresh_rate)
+ scaling_factor = MAX_TG_COLOR_VALUE * (refresh_rate - min_refresh_rate) / (max_refresh_rate - min_refresh_rate);
+
+ pipe_ctx->visual_confirm_color.color_r_cr = color_value;
+ pipe_ctx->visual_confirm_color.color_g_y = scaling_factor;
+ pipe_ctx->visual_confirm_color.color_b_cb = color_value;
+ }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
index 7bb4504889be..f4e99ca7918f 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_exports.c
@@ -46,7 +46,7 @@ struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_index)
void dc_get_edp_links(const struct dc *dc,
struct dc_link **edp_links,
- int *edp_num)
+ unsigned int *edp_num)
{
int i;
@@ -68,7 +68,7 @@ bool dc_get_edp_link_panel_inst(const struct dc *dc,
unsigned int *inst_out)
{
struct dc_link *edp_links[MAX_NUM_EDP];
- int edp_num, i;
+ unsigned int edp_num, i;
*inst_out = 0;
if (link->connector_signal != SIGNAL_TYPE_EDP)
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 03d125f794b0..66597a1f5b78 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -78,6 +78,7 @@
#include "dcn351/dcn351_resource.h"
#include "dcn36/dcn36_resource.h"
#include "dcn401/dcn401_resource.h"
+#include "dcn42/dcn42_resource.h"
#if defined(CONFIG_DRM_AMD_DC_FP)
#include "dc_spl_translate.h"
#endif
@@ -252,6 +253,9 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
ASICREV_IS_GC_12_0_0_A0(asic_id.hw_internal_rev))
dc_version = DCN_VERSION_4_01;
break;
+ case AMDGPU_FAMILY_GC_11_5_4:
+ dc_version = DCN_VERSION_4_2;
+ break;
default:
dc_version = DCE_VERSION_UNKNOWN;
break;
@@ -368,6 +372,9 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc,
case DCN_VERSION_4_01:
res_pool = dcn401_create_resource_pool(init_data, dc);
break;
+ case DCN_VERSION_4_2:
+ res_pool = dcn42_create_resource_pool(init_data, dc);
+ break;
#endif /* CONFIG_DRM_AMD_DC_FP */
default:
break;
@@ -742,10 +749,10 @@ struct clock_source *resource_find_used_clk_src_for_sharing(
return NULL;
}
-static enum pixel_format convert_pixel_format_to_dalsurface(
+static enum dc_pixel_format convert_pixel_format_to_dalsurface(
enum surface_pixel_format surface_pixel_format)
{
- enum pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
+ enum dc_pixel_format dal_pixel_format = PIXEL_FORMAT_UNKNOWN;
switch (surface_pixel_format) {
case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
@@ -1741,6 +1748,7 @@ enum dc_status resource_build_scaling_params_for_context(
const struct dc *dc,
struct dc_state *context)
{
+ (void)dc;
int i;
for (i = 0; i < MAX_PIPES; i++) {
@@ -1818,6 +1826,7 @@ int resource_find_free_pipe_used_as_sec_opp_head_by_cur_otg_master(
struct resource_context *new_res_ctx,
const struct pipe_ctx *cur_otg_master)
{
+ (void)cur_res_ctx;
const struct pipe_ctx *cur_sec_opp_head = cur_otg_master->next_odm_pipe;
struct pipe_ctx *new_pipe;
int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND;
@@ -1839,6 +1848,7 @@ int resource_find_free_pipe_used_in_cur_mpc_blending_tree(
struct resource_context *new_res_ctx,
const struct pipe_ctx *cur_opp_head)
{
+ (void)cur_res_ctx;
const struct pipe_ctx *cur_sec_dpp = cur_opp_head->bottom_pipe;
struct pipe_ctx *new_pipe;
int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND;
@@ -2424,7 +2434,6 @@ static void resource_log_pipe_for_stream(struct dc *dc, struct dc_state *state,
int slice_idx, dpp_idx, plane_idx, slice_count, dpp_count;
bool is_primary;
- DC_LOGGER_INIT(dc->ctx->logger);
slice_count = resource_get_opp_heads_for_otg_master(otg_master,
&state->res_ctx, opp_heads);
@@ -2935,6 +2944,7 @@ enum dc_status resource_add_otg_master_for_stream_output(struct dc_state *new_ct
const struct resource_pool *pool,
struct dc_stream_state *stream)
{
+ (void)pool;
struct dc *dc = stream->ctx->dc;
return dc->res_pool->funcs->add_stream_to_ctx(dc, new_ctx, stream);
@@ -3017,6 +3027,7 @@ static bool add_plane_to_opp_head_pipes(struct pipe_ctx *otg_master_pipe,
struct dc_plane_state *plane_state,
struct dc_state *context)
{
+ (void)context;
struct pipe_ctx *opp_head_pipe = otg_master_pipe;
while (opp_head_pipe) {
@@ -3609,6 +3620,7 @@ static struct hpo_dp_stream_encoder *find_first_free_match_hpo_dp_stream_enc_for
const struct resource_pool *pool,
struct dc_stream_state *stream)
{
+ (void)stream;
int i;
for (i = 0; i < pool->hpo_dp_stream_enc_count; i++) {
@@ -3628,6 +3640,7 @@ static struct audio *find_first_free_audio(
enum engine_id id,
enum dce_version dc_version)
{
+ (void)dc_version;
int i, available_audio_count;
if (id == ENGINE_ID_UNKNOWN)
@@ -5234,7 +5247,7 @@ unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format)
return 64;
default:
ASSERT_CRITICAL(false);
- return -1;
+ return UINT_MAX;
}
}
static unsigned int get_max_audio_sample_rate(struct audio_mode *modes)
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 a40e5c44143f..40f7aa732258 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
@@ -205,19 +205,33 @@ struct dc_state *dc_state_create(struct dc *dc, struct dc_state_create_params *p
state->power_source = params ? params->power_source : DC_POWER_SOURCE_AC;
#ifdef CONFIG_DRM_AMD_DC_FP
+ bool status;
+
if (dc->debug.using_dml2) {
- if (!dml2_create(dc, &dc->dml2_options, &state->bw_ctx.dml2)) {
+ DC_FP_START();
+ status = dml2_create(dc, &dc->dml2_options, &state->bw_ctx.dml2);
+ DC_FP_END();
+
+ if (!status) {
dc_state_release(state);
return NULL;
}
- if (dc->caps.dcmode_power_limits_present && !dml2_create(dc, &dc->dml2_dc_power_options, &state->bw_ctx.dml2_dc_power_source)) {
- dc_state_release(state);
- return NULL;
+ if (dc->caps.dcmode_power_limits_present) {
+ bool status;
+
+ DC_FP_START();
+ status = dml2_create(dc, &dc->dml2_dc_power_options, &state->bw_ctx.dml2_dc_power_source);
+ DC_FP_END();
+
+ if (!status) {
+ dc_state_release(state);
+ return NULL;
+ }
}
- }
-#endif
+ }
+#endif // CONFIG_DRM_AMD_DC_FP
kref_init(&state->refcount);
return state;
@@ -235,14 +249,20 @@ void dc_state_copy(struct dc_state *dst_state, struct dc_state *src_state)
#ifdef CONFIG_DRM_AMD_DC_FP
dst_state->bw_ctx.dml2 = dst_dml2;
- if (src_state->bw_ctx.dml2)
+ if (src_state->bw_ctx.dml2) {
+ DC_FP_START();
dml2_copy(dst_state->bw_ctx.dml2, src_state->bw_ctx.dml2);
+ DC_FP_END();
+ }
dst_state->bw_ctx.dml2_dc_power_source = dst_dml2_dc_power_source;
- if (src_state->bw_ctx.dml2_dc_power_source)
- dml2_copy(dst_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source);
-#endif
+ if (src_state->bw_ctx.dml2_dc_power_source) {
+ DC_FP_START();
+ dml2_copy(dst_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source);
+ DC_FP_END();
+ }
+#endif // CONFIG_DRM_AMD_DC_FP
/* context refcount should not be overridden */
dst_state->refcount = refcount;
}
@@ -258,22 +278,35 @@ struct dc_state *dc_state_create_copy(struct dc_state *src_state)
dc_state_copy_internal(new_state, src_state);
#ifdef CONFIG_DRM_AMD_DC_FP
+ bool status;
+
new_state->bw_ctx.dml2 = NULL;
new_state->bw_ctx.dml2_dc_power_source = NULL;
- if (src_state->bw_ctx.dml2 &&
- !dml2_create_copy(&new_state->bw_ctx.dml2, src_state->bw_ctx.dml2)) {
- dc_state_release(new_state);
- return NULL;
- }
+ if (src_state->bw_ctx.dml2) {
+ DC_FP_START();
+ status = dml2_create_copy(&new_state->bw_ctx.dml2, src_state->bw_ctx.dml2);
+ DC_FP_END();
- if (src_state->bw_ctx.dml2_dc_power_source &&
- !dml2_create_copy(&new_state->bw_ctx.dml2_dc_power_source, src_state->bw_ctx.dml2_dc_power_source)) {
- dc_state_release(new_state);
- return NULL;
+ if (!status) {
+ dc_state_release(new_state);
+ return NULL;
+ }
}
-#endif
+
+ if (src_state->bw_ctx.dml2_dc_power_source) {
+ DC_FP_START();
+ status = dml2_create_copy(&new_state->bw_ctx.dml2_dc_power_source,
+ src_state->bw_ctx.dml2_dc_power_source);
+ DC_FP_END();
+
+ if (!status) {
+ dc_state_release(new_state);
+ return NULL;
+ }
+ }
+#endif // CONFIG_DRM_AMD_DC_FP
kref_init(&new_state->refcount);
return new_state;
@@ -351,11 +384,13 @@ static void dc_state_free(struct kref *kref)
dc_state_destruct(state);
#ifdef CONFIG_DRM_AMD_DC_FP
+ DC_FP_START();
dml2_destroy(state->bw_ctx.dml2);
state->bw_ctx.dml2 = 0;
dml2_destroy(state->bw_ctx.dml2_dc_power_source);
state->bw_ctx.dml2_dc_power_source = 0;
+ DC_FP_END();
#endif
kvfree(state);
@@ -374,6 +409,7 @@ enum dc_status dc_state_add_stream(
struct dc_state *state,
struct dc_stream_state *stream)
{
+ (void)dc;
enum dc_status res;
DC_LOGGER_INIT(dc->ctx->logger);
@@ -749,6 +785,7 @@ struct dc_plane_state *dc_state_create_phantom_plane(const struct dc *dc,
struct dc_state *state,
struct dc_plane_state *main_plane)
{
+ (void)main_plane;
struct dc_plane_state *phantom_plane = dc_create_plane_state(dc);
DC_LOGGER_INIT(dc->ctx->logger);
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 baf820e6eae8..e16de323f39c 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -42,6 +42,13 @@
#define MAX(x, y) ((x > y) ? x : y)
#endif
+#include "dc_fpu.h"
+
+#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED)
+#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
+#endif // !DC_RUN_WITH_PREEMPTION_ENABLED
+
+
/*******************************************************************************
* Private functions
******************************************************************************/
@@ -170,11 +177,15 @@ struct dc_stream_state *dc_create_stream_for_sink(
if (sink == NULL)
goto fail;
- stream = kzalloc_obj(struct dc_stream_state, GFP_ATOMIC);
+ DC_RUN_WITH_PREEMPTION_ENABLED(stream = kzalloc_obj(struct dc_stream_state, GFP_ATOMIC));
+
if (stream == NULL)
goto fail;
- stream->update_scratch = kzalloc((int32_t) dc_update_scratch_space_size(), GFP_ATOMIC);
+ DC_RUN_WITH_PREEMPTION_ENABLED(stream->update_scratch =
+ kzalloc((int32_t) dc_update_scratch_space_size(),
+ GFP_ATOMIC));
+
if (stream->update_scratch == NULL)
goto fail;
@@ -245,7 +256,6 @@ const struct dc_stream_status *dc_stream_get_status_const(
const struct dc_stream_state *stream)
{
struct dc *dc = stream->ctx->dc;
-
return dc_state_get_stream_status(dc->current_state, stream);
}
@@ -523,8 +533,10 @@ bool dc_stream_program_cursor_position(
struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
/* trigger event on first pipe with current stream */
- if (stream == pipe_ctx->stream) {
- pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg);
+ if (stream == pipe_ctx->stream &&
+ pipe_ctx->stream_res.tg->funcs->program_manual_trigger) {
+ pipe_ctx->stream_res.tg->funcs->program_manual_trigger(
+ pipe_ctx->stream_res.tg);
break;
}
}
@@ -984,7 +996,6 @@ void dc_stream_release_3dlut_for_stream(
if (rmcm_3dlut) {
rmcm_3dlut->isInUse = false;
rmcm_3dlut->stream = NULL;
- rmcm_3dlut->protection_bits = 0;
}
}
@@ -996,7 +1007,6 @@ void dc_stream_init_rmcm_3dlut(struct dc *dc)
for (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/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
index d4c40b44d909..a59b176d8e55 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
@@ -57,6 +57,7 @@ void dc_plane_construct(struct dc_context *ctx, struct dc_plane_state *plane_sta
void dc_plane_destruct(struct dc_plane_state *plane_state)
{
+ (void)plane_state;
// no more pointers to free within dc_plane_state
}
@@ -139,6 +140,9 @@ const struct dc_plane_status *dc_plane_get_status(
if (pipe_ctx->plane_state && flags.bits.address)
pipe_ctx->plane_state->status.is_flip_pending = false;
+ if (pipe_ctx->plane_state && flags.bits.histogram)
+ memset(&pipe_ctx->plane_state->status.cm_hist, 0,
+ sizeof(pipe_ctx->plane_state->status.cm_hist));
break;
}
@@ -154,6 +158,12 @@ const struct dc_plane_status *dc_plane_get_status(
if (flags.bits.address)
dc->hwss.update_pending_status(pipe_ctx);
+ if (flags.bits.histogram) {
+ struct dpp *dpp = pipe_ctx->plane_res.dpp;
+
+ if (dpp && dpp->funcs->dpp_cm_hist_read)
+ dpp->funcs->dpp_cm_hist_read(dpp, &pipe_ctx->plane_state->status.cm_hist);
+ }
}
return plane_status;
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 4c4239cac863..55ec281db3b7 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-2023 Advanced Micro Devices, Inc.
+ * Copyright 2012-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -63,7 +63,7 @@ struct dcn_dsc_reg_state;
struct dcn_optc_reg_state;
struct dcn_dccg_reg_state;
-#define DC_VER "3.2.369"
+#define DC_VER "3.2.376"
/**
* MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC
@@ -520,7 +520,7 @@ struct dc_config {
union allow_lttpr_non_transparent_mode allow_lttpr_non_transparent_mode;
bool multi_mon_pp_mclk_switch;
bool disable_dmcu;
- bool enable_4to1MPC;
+ bool allow_4to1MPC;
bool enable_windowed_mpo_odm;
bool forceHBR2CP2520; // Used for switching between test patterns TPS4 and CP2520
uint32_t allow_edp_hotplug_detection;
@@ -581,6 +581,7 @@ enum visual_confirm {
VISUAL_CONFIRM_HW_CURSOR = 20,
VISUAL_CONFIRM_VABC = 21,
VISUAL_CONFIRM_DCC = 22,
+ VISUAL_CONFIRM_BOOSTED_REFRESH_RATE = 23,
VISUAL_CONFIRM_EXPLICIT = 0x80000000,
};
@@ -733,6 +734,8 @@ struct dc_clocks {
struct {
uint8_t base_efficiency; //LP1
uint8_t low_power_efficiency; //LP2
+ uint8_t z8_stutter_efficiency;
+ int z8_stutter_period;
} stutter_efficiency;
};
@@ -1211,6 +1214,8 @@ struct dc_debug_options {
unsigned int num_fast_flips_to_steady_state_override;
bool enable_dmu_recovery;
unsigned int force_vmin_threshold;
+ bool enable_otg_frame_sync_pwa;
+ unsigned int min_deep_sleep_dcfclk_khz;
};
@@ -1400,15 +1405,50 @@ 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;
};
+
+/* 3DLUT DMA (Fast Load) params */
+struct dc_3dlut_dma {
+ struct dc_plane_address addr;
+ enum dc_cm_lut_swizzle swizzle;
+ enum dc_cm_lut_pixel_format format;
+ uint16_t bias; /* FP1.5.10 */
+ uint16_t scale; /* FP1.5.10 */
+ enum dc_cm_lut_size size;
+};
+
+/* color manager */
+union dc_plane_cm_flags {
+ unsigned int all;
+ struct {
+ unsigned int shaper_enable : 1;
+ unsigned int lut3d_enable : 1;
+ unsigned int blend_enable : 1;
+ /* whether legacy (lut3d_func) or DMA is valid */
+ unsigned int lut3d_dma_enable : 1;
+ /* RMCM lut to be used instead of MCM */
+ unsigned int rmcm_enable : 1;
+ unsigned int reserved: 27;
+ } bits;
+};
+
+struct dc_plane_cm {
+ struct kref refcount;
+ struct dc_transfer_func shaper_func;
+ union {
+ struct dc_3dlut lut3d_func;
+ struct dc_3dlut_dma lut3d_dma;
+ };
+ struct dc_transfer_func blend_func;
+ union dc_plane_cm_flags flags;
+};
+
/*
* This structure is filled in by dc_surface_get_status and contains
* the last requested address and the currently active address so the called
@@ -1419,6 +1459,7 @@ struct dc_plane_status {
struct dc_plane_address current_address;
bool is_flip_pending;
bool is_right_eye;
+ struct cm_hist cm_hist;
};
union surface_update_flags {
@@ -1455,6 +1496,7 @@ union surface_update_flags {
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;
} bits;
uint32_t raw;
@@ -1484,14 +1526,18 @@ struct dc_plane_state {
struct fixed31_32 hdr_mult;
struct colorspace_transform gamut_remap_matrix;
- // TODO: No longer used, remove
- struct dc_hdr_static_metadata hdr_static_ctx;
-
enum dc_color_space color_space;
+ 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;
+ enum mpcc_movable_cm_location mcm_location;
+ struct dc_plane_cm cm;
struct dc_transfer_func *gamcor_tf;
enum surface_pixel_format format;
@@ -1528,17 +1574,13 @@ struct dc_plane_state {
bool is_statically_allocated;
enum chroma_cositing cositing;
- enum dc_cm2_shaper_3dlut_setting mcm_shaper_3dlut_setting;
- bool mcm_lut1d_enable;
- struct dc_cm2_func_luts mcm_luts;
- bool lut_bank_a;
- enum mpcc_movable_cm_location mcm_location;
struct dc_csc_transform cursor_csc_color_matrix;
bool adaptive_sharpness_en;
int adaptive_sharpness_policy;
int sharpness_level;
enum linear_light_scaling linear_light_scaling;
unsigned int sdr_white_level_nits;
+ struct cm_hist_control cm_hist_control;
struct spl_sharpness_range sharpness_range;
enum sharpness_range_source sharpness_source;
};
@@ -1682,6 +1724,10 @@ struct dc_scratch_space {
struct panel_cntl *panel_cntl;
struct link_encoder *link_enc;
struct graphics_object_id link_id;
+
+ /* External encoder eg. NUTMEG or TRAVIS used on CIK APUs. */
+ struct graphics_object_id ext_enc_id;
+
/* Endpoint type distinguishes display endpoints which do not have entries
* in the BIOS connector table from those that do. Helps when tracking link
* encoder to display endpoint assignments.
@@ -1843,6 +1889,9 @@ struct dc_fast_update {
struct dc_transfer_func *out_transfer_func;
struct dc_csc_transform *output_csc_transform;
const struct dc_csc_transform *cursor_csc_color_matrix;
+#if defined(CONFIG_DRM_AMD_DC_DCN4_2)
+ struct cm_hist_control *cm_hist_control;
+#endif
};
struct dc_surface_update {
@@ -1872,9 +1921,11 @@ struct dc_surface_update {
* change cm2_params.cm2_luts: Fast update
*/
const struct dc_cm2_parameters *cm2_params;
+ const struct dc_plane_cm *cm;
const struct dc_csc_transform *cursor_csc_color_matrix;
unsigned int sdr_white_level_nits;
struct dc_bias_and_scale bias_and_scale;
+ struct cm_hist_control *cm_hist_control;
};
struct dc_underflow_debug_data {
@@ -1915,9 +1966,22 @@ struct dc_3dlut *dc_create_3dlut_func(void);
void dc_3dlut_func_release(struct dc_3dlut *lut);
void dc_3dlut_func_retain(struct dc_3dlut *lut);
+struct dc_plane_cm *dc_plane_cm_create(void);
+void dc_plane_cm_release(struct dc_plane_cm *cm);
+void dc_plane_cm_retain(struct dc_plane_cm *cm);
+
void dc_post_update_surfaces_to_stream(
struct dc *dc);
+/*
+ * dc_get_default_tiling_info() - Retrieve an ASIC-appropriate default tiling
+ * description for (typically) linear surfaces.
+ *
+ * This is used by OS/DM paths that need a valid, fully-initialized tiling
+ * description without hardcoding gfx-version specifics in the caller.
+ */
+void dc_get_default_tiling_info(const struct dc *dc, struct dc_tiling_info *tiling_info);
+
/**
* struct dc_validation_set - Struct to store surface/stream associations for validation
*/
@@ -2016,7 +2080,7 @@ bool dc_get_edp_link_panel_inst(const struct dc *dc,
/* Return an array of link pointers to edp links. */
void dc_get_edp_links(const struct dc *dc,
struct dc_link **edp_links,
- int *edp_num);
+ unsigned int *edp_num);
void dc_set_edp_power(const struct dc *dc, struct dc_link *edp_link,
bool powerOn);
diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h
index 40d7a7d83c40..6f96c5cf39fe 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h
@@ -97,11 +97,12 @@ struct dc_vbios_funcs {
enum bp_result (*encoder_control)(
struct dc_bios *bios,
struct bp_encoder_control *cntl);
+ enum bp_result (*external_encoder_control)(
+ struct dc_bios *bios,
+ struct bp_external_encoder_control *cntl);
enum bp_result (*dac_load_detection)(
struct dc_bios *bios,
- enum engine_id engine_id,
- enum dal_device_type device_type,
- uint32_t enum_id);
+ enum engine_id engine_id);
enum bp_result (*transmitter_control)(
struct dc_bios *bios,
struct bp_transmitter_control *cntl);
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 b15360bcdacf..79c8b4cab053 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -958,7 +958,10 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)
{
uint32_t i;
- if (!dc_dmub_srv || !dc_dmub_srv->dmub) {
+ if (!dc_dmub_srv)
+ return;
+
+ if (!dc_dmub_srv->dmub) {
DC_LOG_ERROR("%s: invalid parameters.", __func__);
return;
}
@@ -1082,6 +1085,7 @@ static void dc_build_cursor_attribute_update_payload1(
struct dmub_cursor_attributes_cfg *pl_A, const uint8_t p_idx,
const struct hubp *hubp, const struct dpp *dpp)
{
+ (void)p_idx;
/* Hubp */
pl_A->aHubp.SURFACE_ADDR_HIGH = hubp->att.SURFACE_ADDR_HIGH;
pl_A->aHubp.SURFACE_ADDR = hubp->att.SURFACE_ADDR;
@@ -1163,7 +1167,10 @@ void dc_dmub_srv_enable_dpia_trace(const struct dc *dc)
{
struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv;
- if (!dc_dmub_srv || !dc_dmub_srv->dmub) {
+ if (!dc_dmub_srv)
+ return;
+
+ if (!dc_dmub_srv->dmub) {
DC_LOG_ERROR("%s: invalid parameters.", __func__);
return;
}
@@ -2349,6 +2356,33 @@ bool dc_dmub_srv_is_cursor_offload_enabled(const struct dc *dc)
return dc->ctx->dmub_srv && dc->ctx->dmub_srv->cursor_offload_enabled;
}
+void dc_dmub_srv_boot_time_crc_init(const struct dc *dc, uint64_t gpu_addr, uint32_t size)
+{
+ struct dc_dmub_srv *dc_dmub_srv;
+ struct dc_context *dc_ctx;
+ union dmub_rb_cmd cmd = {0};
+ bool result = false;
+
+ if (!dc || !dc->ctx || !dc->ctx->dmub_srv || size == 0)
+ return;
+
+ dc_dmub_srv = dc->ctx->dmub_srv;
+ dc_ctx = dc_dmub_srv->ctx;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.boot_time_crc_init.header.type = DMUB_CMD__BOOT_TIME_CRC;
+ cmd.boot_time_crc_init.header.sub_type = DMUB_CMD__BOOT_TIME_CRC_INIT_MEM;
+ cmd.boot_time_crc_init.header.payload_bytes =
+ sizeof(struct dmub_rb_cmd_boot_time_crc_init);
+ cmd.boot_time_crc_init.data.buffer_addr.quad_part = gpu_addr;
+ cmd.boot_time_crc_init.data.buffer_size = size;
+
+ result = dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
+
+ if (!result)
+ DC_ERROR("Boot time crc init failed in DMUB");
+}
+
void dc_dmub_srv_release_hw(const struct dc *dc)
{
struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv;
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 72e0a41f39f0..6579cf9cce3c 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
@@ -362,6 +362,15 @@ void dc_dmub_srv_program_cursor_now(struct dc *dc, const struct pipe_ctx *pipe);
bool dc_dmub_srv_is_cursor_offload_enabled(const struct dc *dc);
/**
+ * dc_dmub_srv_boot_time_crc_init() - Initializes DMUB boot time CRC.
+ *
+ * @dc - pointer to DC object
+ * @gpu_addr - address for the boot time CRC buffer
+ * @size - size of the boot time CRC buffer
+ */
+void dc_dmub_srv_boot_time_crc_init(const struct dc *dc, uint64_t gpu_addr, uint32_t size);
+
+/**
* dc_dmub_srv_release_hw() - Notifies DMUB service that HW access is no longer required.
*
* @dc - pointer to DC object
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
index 5e3646b7550c..7fa336bf1115 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dp_types.h
@@ -947,8 +947,8 @@ union dp_tun_cap_support {
/* DPCD[0xE000E] DP_IN_ADAPTER_INFO register. */
union dpia_info {
struct {
- uint8_t dpia_num :5;
- uint8_t rsvd :3;
+ uint8_t dpia_num :6;
+ uint8_t rsvd :2;
} bits;
uint8_t raw;
};
@@ -1374,7 +1374,7 @@ union dpcd_replay_configuration {
unsigned char DESYNC_ERROR_STATUS : 1;
unsigned char SINK_DEVICE_REPLAY_STATUS : 3;
unsigned char SINK_FRAME_LOCKED : 2;
- unsigned char RESERVED : 1;
+ unsigned char FRAME_SKIPPING_ERROR_STATUS : 1;
} bits;
unsigned char raw;
};
diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c
index 5a365bd19933..77299767096f 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c
@@ -108,6 +108,7 @@ static void set_reg_field_values(struct dc_reg_value_masks *field_value_mask,
uint8_t shift1, uint32_t mask1, uint32_t field_value1,
va_list ap)
{
+ (void)addr;
uint32_t shift, mask, field_value;
int i = 1;
@@ -751,6 +752,8 @@ char *dce_version_to_string(const int version)
return "DCN 3.6";
case DCN_VERSION_4_01:
return "DCN 4.0.1";
+ case DCN_VERSION_4_2:
+ return "DCN 4.2";
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 cfa569a7bff1..c2ca08d26e37 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -218,7 +218,7 @@ enum surface_pixel_format {
/* Pixel format */
-enum pixel_format {
+enum dc_pixel_format {
/*graph*/
PIXEL_FORMAT_UNINITIALIZED,
PIXEL_FORMAT_INDEX8,
@@ -271,6 +271,15 @@ enum tile_split_values_new {
DC_SURF_TILE_SPLIT_1KB = 0x4,
};
+enum otg_pwa_sync_mode {
+ DC_OTG_PWA_FRAME_SYNC_MODE_VSYNC = 0x0,
+ DC_OTG_PWA_FRAME_SYNC_MODE_VSTARTUP = 0x1,
+};
+struct otc_pwa_frame_sync {
+ enum otg_pwa_sync_mode pwa_sync_mode;
+ uint32_t pwa_frame_sync_line_offset;
+};
+
/* TODO: These values come from hardware spec. We need to readdress this
* if they ever change.
*/
@@ -436,6 +445,10 @@ enum dc_gfxversion {
enum swizzle_mode_addr3_values swizzle;
} gfx_addr3;/*gfx with addr3 and above*/
};
+
+ struct {
+ bool avoid_full_update_on_tiling_change;
+ } flags;
};
/* Rotation angle */
@@ -1137,6 +1150,7 @@ struct mcif_buf_params {
unsigned int warmup_pitch;
unsigned int swlock;
unsigned int p_vmid;
+ uint8_t tmz_id;
};
@@ -1162,5 +1176,68 @@ struct phy_state {
enum symclk_state symclk_state;
};
+enum cm_hist_tap_point {
+ CM_HIST_TAP_POINT_1,
+ CM_HIST_TAP_POINT_2,
+ CM_HIST_TAP_POINT_3,
+ CM_HIST_TAP_POINT_4,
+};
+
+enum cm_hist_src {
+ CM_HIST_SRC1,
+ CM_HIST_SRC2,
+ CM_HIST_SRC3,
+};
+
+enum cm_hist_format {
+ CM_HIST_FORMAT_FIXED_POINT,
+ CM_HIST_FORMAT_FP16_POS,
+ CM_HIST_FORMAT_FP16_POS_AND_NEG,
+};
+
+enum cm_hist_read_channel_mask {
+ CM_HIST_READ_DISABLED,
+ CM_HIST_READ_CH1,
+ CM_HIST_READ_CH2,
+ CM_HIST_READ_CH1_CH2,
+ CM_HIST_READ_CH3,
+ CM_HIST_READ_CH1_CH3,
+ CM_HIST_READ_CH2_CH3,
+ CM_HIST_READ_ALL,
+};
+
+enum cm_hist_src1_mode {
+ CM_HIST_SRC1_MODE_R_OR_CR,
+ CM_HIST_SRC1_MODE_MAX_RGB,
+};
+
+enum cm_hist_src2_mode {
+ CM_HIST_SRC2_MODE_G_OR_Y,
+ CM_HIST_SRC2_MODE_RGB_TO_Y,
+};
+
+enum cm_hist_src3_mode {
+ CM_HIST_SRC3_MODE_B_OR_CB,
+ CM_HIST_SRC3_MODE_MIN_RGB,
+};
+
+struct cm_hist_control {
+ enum cm_hist_tap_point tap_point;
+ uint32_t channels_enabled;
+ enum cm_hist_src1_mode src_1_select;
+ enum cm_hist_src2_mode src_2_select;
+ enum cm_hist_src3_mode src_3_select;
+ enum cm_hist_src ch1_src;
+ enum cm_hist_src ch2_src;
+ enum cm_hist_src ch3_src;
+ enum cm_hist_format format;
+ enum cm_hist_read_channel_mask read_channel_mask;
+};
+
+struct cm_hist {
+ uint32_t ch1[256];
+ uint32_t ch2[256];
+ uint32_t ch3[256];
+};
#endif /* DC_HW_TYPES_H */
diff --git a/drivers/gpu/drm/amd/display/dc/dc_plane.h b/drivers/gpu/drm/amd/display/dc/dc_plane.h
index 14feb843e694..2ad6d9318566 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_plane.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_plane.h
@@ -31,6 +31,7 @@
union dc_plane_status_update_flags {
struct {
uint32_t address : 1;
+ uint32_t histogram : 1;
} bits;
uint32_t raw;
};
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 37d1a79e8241..52ed8deebf63 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
@@ -63,7 +63,8 @@ static void populate_inits_from_splinits(struct scl_inits *inits,
inits->h_c = dc_fixpt_from_int_dy(spl_inits->h_filter_init_int_c, spl_inits->h_filter_init_frac_c >> 5, 0, 19);
inits->v_c = dc_fixpt_from_int_dy(spl_inits->v_filter_init_int_c, spl_inits->v_filter_init_frac_c >> 5, 0, 19);
}
-static void populate_splformat_from_format(enum spl_pixel_format *spl_pixel_format, const enum pixel_format pixel_format)
+static void populate_splformat_from_format(enum spl_pixel_format *spl_pixel_format,
+ const enum dc_pixel_format pixel_format)
{
if (pixel_format < PIXEL_FORMAT_INVALID)
*spl_pixel_format = (enum spl_pixel_format)pixel_format;
@@ -89,6 +90,7 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl
spl_in->callbacks = dcn32_spl_callbacks;
break;
case DCN_VERSION_4_01:
+ case DCN_VERSION_4_2:
spl_in->callbacks = dcn401_spl_callbacks;
break;
default:
diff --git a/drivers/gpu/drm/amd/display/dc/dc_trace.h b/drivers/gpu/drm/amd/display/dc/dc_trace.h
index bbec308a3a5e..b7a011646d53 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_trace.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_trace.h
@@ -23,8 +23,8 @@
#include "amdgpu_dm_trace.h"
-#define TRACE_DC_PIPE_STATE(pipe_ctx, index, max_pipes) \
- for (index = 0; index < max_pipes; ++index) { \
+#define TRACE_DC_PIPE_STATE(pipe_ctx, max_pipes) \
+ for (int index = 0; index < max_pipes; ++index) { \
struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[index]; \
if (pipe_ctx->plane_state) \
trace_amdgpu_dm_dc_pipe_state(pipe_ctx->pipe_idx, pipe_ctx->plane_state, \
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index bddb16bb76d4..fd8ec1660312 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
+ * Copyright 2012-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -1144,10 +1144,12 @@ union replay_low_refresh_rate_enable_options {
union replay_optimization {
struct {
- //BIT[0-3]: Replay Teams Optimization
+ //BIT[0-1]: Replay Teams Optimization
unsigned int TEAMS_OPTIMIZATION_VER_1 :1;
unsigned int TEAMS_OPTIMIZATION_VER_2 :1;
- unsigned int RESERVED_2_3 :2;
+ //BIT[2]: Replay Live Capture with CVT
+ unsigned int LIVE_CAPTURE_WITH_CVT :1;
+ unsigned int RESERVED_3 :1;
} bits;
unsigned int raw;
@@ -1194,6 +1196,10 @@ struct replay_config {
union replay_optimization replay_optimization;
/* Replay sub feature Frame Skipping is supported */
bool frame_skip_supported;
+ /* Replay Received Frame Skipping Error HPD. */
+ bool received_frame_skipping_error_hpd;
+ /* Live capture with CVT is activated */
+ bool live_capture_with_cvt_activated;
};
/* Replay feature flags*/
@@ -1346,6 +1352,7 @@ enum dc_cm2_gpu_mem_layout {
enum dc_cm2_gpu_mem_pixel_component_order {
DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA,
+ DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_BGRA
};
enum dc_cm2_gpu_mem_format {
@@ -1367,6 +1374,9 @@ struct dc_cm2_gpu_mem_format_parameters {
enum dc_cm2_gpu_mem_size {
DC_CM2_GPU_MEM_SIZE_171717,
+ DC_CM2_GPU_MEM_SIZE_333333,
+ DC_CM2_GPU_MEM_SIZE_454545,
+ DC_CM2_GPU_MEM_SIZE_656565,
DC_CM2_GPU_MEM_SIZE_TRANSFORMED,
};
@@ -1477,4 +1487,28 @@ struct dc_validation_dpia_set {
uint32_t required_bw;
};
+enum dc_cm_lut_swizzle {
+ CM_LUT_3D_SWIZZLE_LINEAR_RGB,
+ CM_LUT_3D_SWIZZLE_LINEAR_BGR,
+ CM_LUT_1D_PACKED_LINEAR
+};
+
+enum dc_cm_lut_pixel_format {
+ CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12MSB,
+ CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12MSB,
+ CM_LUT_PIXEL_FORMAT_RGBA16161616_UNORM_12LSB,
+ CM_LUT_PIXEL_FORMAT_BGRA16161616_UNORM_12LSB,
+ CM_LUT_PIXEL_FORMAT_RGBA16161616_FLOAT_FP1_5_10,
+ CM_LUT_PIXEL_FORMAT_BGRA16161616_FLOAT_FP1_5_10
+};
+
+enum dc_cm_lut_size {
+ CM_LUT_SIZE_NONE,
+ CM_LUT_SIZE_999,
+ CM_LUT_SIZE_171717,
+ CM_LUT_SIZE_333333,
+ CM_LUT_SIZE_454545,
+ CM_LUT_SIZE_656565,
+};
+
#endif /* DC_TYPES_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/Makefile b/drivers/gpu/drm/amd/display/dc/dccg/Makefile
index 1d5cf0f8e79d..bf7e71166b5e 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dccg/Makefile
@@ -1,5 +1,5 @@
-# Copyright 2022 Advanced Micro Devices, Inc.
+# Copyright 2022-2026 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -100,4 +100,13 @@ DCCG_DCN401 = dcn401_dccg.o
AMD_DAL_DCCG_DCN401 = $(addprefix $(AMDDALPATH)/dc/dccg/dcn401/,$(DCCG_DCN401))
AMD_DISPLAY_FILES += $(AMD_DAL_DCCG_DCN401)
+
+###############################################################################
+# DCN42
+###############################################################################
+DCCG_DCN42 = dcn42_dccg.o
+
+AMD_DAL_DCCG_DCN42 = $(addprefix $(AMDDALPATH)/dc/dccg/dcn42/,$(DCCG_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DCCG_DCN42)
endif
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 4c4e61bc91b5..088cf305a772 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Advanced Micro Devices, Inc.
+ * Copyright 2018-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -366,6 +366,17 @@
type SYMCLK32_LE3_EN;\
type DP_DTO_ENABLE[MAX_PIPES];
+#define DCCG42_REG_FIELD_LIST(type) \
+ type OTG0_ADD_PIXEL;\
+ type OTG1_ADD_PIXEL;\
+ type OTG2_ADD_PIXEL;\
+ type OTG0_DROP_PIXEL;\
+ type OTG1_DROP_PIXEL;\
+ type OTG2_DROP_PIXEL;\
+ type OTG3_ADD_PIXEL;\
+ type OTG3_DROP_PIXEL;\
+ type RESYNC_FIFO_LEVEL_ADJUST_EN;
+
struct dccg_shift {
DCCG_REG_FIELD_LIST(uint8_t)
DCCG3_REG_FIELD_LIST(uint8_t)
@@ -374,6 +385,7 @@ struct dccg_shift {
DCCG32_REG_FIELD_LIST(uint8_t)
DCCG35_REG_FIELD_LIST(uint8_t)
DCCG401_REG_FIELD_LIST(uint8_t)
+ DCCG42_REG_FIELD_LIST(uint8_t)
};
struct dccg_mask {
@@ -384,6 +396,7 @@ struct dccg_mask {
DCCG32_REG_FIELD_LIST(uint32_t)
DCCG35_REG_FIELD_LIST(uint32_t)
DCCG401_REG_FIELD_LIST(uint32_t)
+ DCCG42_REG_FIELD_LIST(uint32_t)
};
#define DCCG_REG_VARIABLE_LIST \
@@ -497,6 +510,7 @@ struct dccg_mask {
struct dccg_registers {
DCCG_REG_VARIABLE_LIST;
+ uint32_t OTG_ADD_DROP_PIXEL_CNTL;
};
struct dcn_dccg {
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c
index 7f58acfe1177..a72bf413fad6 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn31/dcn31_dccg.c
@@ -165,6 +165,7 @@ void dccg31_set_dpstreamclk(
int otg_inst,
int dp_hpo_inst)
{
+ (void)dp_hpo_inst;
if (src == REFCLK)
dccg31_disable_dpstreamclk(dccg, otg_inst);
else
@@ -644,6 +645,7 @@ void dccg31_get_dccg_ref_freq(struct dccg *dccg,
unsigned int xtalin_freq_inKhz,
unsigned int *dccg_ref_freq_inKhz)
{
+ (void)dccg;
/*
* Assume refclk is sourced from xtalin
* expect 24MHz
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c
index e817cd7c2b6a..18b9c5ceed43 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn32/dcn32_dccg.c
@@ -265,6 +265,7 @@ static void dccg32_get_dccg_ref_freq(struct dccg *dccg,
unsigned int xtalin_freq_inKhz,
unsigned int *dccg_ref_freq_inKhz)
{
+ (void)dccg;
/*
* Assume refclk is sourced from xtalin
* expect 100MHz
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
index 0b7908fbb115..efac64165ccd 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
@@ -558,6 +558,7 @@ static void dccg35_set_symclk32_se_src_new(
static int
dccg35_is_symclk32_se_src_functional_le_new(struct dccg *dccg, int symclk_32_se_inst, int symclk_32_le_inst)
{
+ (void)symclk_32_se_inst;
uint32_t en;
uint32_t src_sel;
@@ -2373,6 +2374,7 @@ static void dccg35_disable_symclk_se_cb(
uint32_t stream_enc_inst,
uint32_t link_enc_inst)
{
+ (void)link_enc_inst;
dccg35_disable_symclk_fe_new(dccg, stream_enc_inst);
/* DMU PHY sequence switches SYMCLK_BE (link_enc_inst) to ref clock once PHY is turned off */
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
index a37f94dec6f2..97605a416031 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c
@@ -161,6 +161,7 @@ void dccg401_set_pixel_rate_div(
enum pixel_rate_div tmds_div,
enum pixel_rate_div unused)
{
+ (void)unused;
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
uint32_t cur_tmds_div = PIXEL_RATE_DIV_NA;
uint32_t dp_dto_int;
@@ -353,6 +354,7 @@ void dccg401_get_dccg_ref_freq(struct dccg *dccg,
unsigned int xtalin_freq_inKhz,
unsigned int *dccg_ref_freq_inKhz)
{
+ (void)dccg;
/*
* Assume refclk is sourced from xtalin
* expect 100MHz
@@ -526,10 +528,6 @@ static void dccg401_enable_dpstreamclk(struct dccg *dccg, int otg_inst, int dp_h
BREAK_TO_DEBUGGER();
return;
}
- if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream)
- REG_UPDATE_2(DCCG_GATE_DISABLE_CNTL3,
- DPSTREAMCLK_GATE_DISABLE, 1,
- DPSTREAMCLK_ROOT_GATE_DISABLE, 1);
}
void dccg401_disable_dpstreamclk(struct dccg *dccg, int dp_hpo_inst)
@@ -725,6 +723,7 @@ void dccg401_init(struct dccg *dccg)
void dccg401_set_dto_dscclk(struct dccg *dccg, uint32_t inst, uint32_t num_slices_h)
{
+ (void)num_slices_h;
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
switch (inst) {
@@ -827,11 +826,22 @@ void dccg401_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint3
if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se)
REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, 1);
break;
+ case 4:
+ if (dccg_dcn->dccg_mask->SYMCLKE_FE_ROOT_GATE_DISABLE) {
+ REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE,
+ SYMCLKE_FE_EN, 1,
+ SYMCLKE_FE_SRC_SEL, link_enc_inst);
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, 1);
+ }
+ break;
+ default:
+ return;
}
}
void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst)
{
+ (void)link_enc_inst;
struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
switch (stream_enc_inst) {
@@ -855,6 +865,16 @@ void dccg401_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, uint
SYMCLKD_FE_EN, 0,
SYMCLKD_FE_SRC_SEL, 0);
break;
+ case 4:
+ if (dccg_dcn->dccg_mask->SYMCLKE_FE_ROOT_GATE_DISABLE) {
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, 0);
+ REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE,
+ SYMCLKE_FE_EN, 0,
+ SYMCLKE_FE_SRC_SEL, 0);
+ }
+ break;
+ default:
+ return;
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c
new file mode 100644
index 000000000000..b813310763e5
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.c
@@ -0,0 +1,334 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "reg_helper.h"
+#include "core_types.h"
+#include "dcn35/dcn35_dccg.h"
+#include "dcn42_dccg.h"
+
+#define TO_DCN_DCCG(dccg)\
+ container_of(dccg, struct dcn_dccg, base)
+
+#define REG(reg) \
+ (dccg_dcn->regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+ dccg_dcn->dccg_shift->field_name, dccg_dcn->dccg_mask->field_name
+
+#define CTX \
+ dccg_dcn->base.ctx
+#define DC_LOGGER \
+ dccg->ctx->logger
+
+void dccg42_otg_add_pixel(struct dccg *dccg,
+ uint32_t otg_inst)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ switch (otg_inst) {
+ case 0:
+ REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+ OTG0_ADD_PIXEL, 1);
+ break;
+ case 1:
+ REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+ OTG1_ADD_PIXEL, 1);
+ break;
+ case 2:
+ REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+ OTG2_ADD_PIXEL, 1);
+ break;
+ case 3:
+ REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+ OTG3_ADD_PIXEL, 1);
+ break;
+ default:
+ ASSERT(0);
+ }
+}
+
+void dccg42_otg_drop_pixel(struct dccg *dccg,
+ uint32_t otg_inst)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ switch (otg_inst) {
+ case 0:
+ REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+ OTG0_DROP_PIXEL, 1);
+ break;
+ case 1:
+ REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+ OTG1_DROP_PIXEL, 1);
+ break;
+ case 2:
+ REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+ OTG2_DROP_PIXEL, 1);
+ break;
+ case 3:
+ REG_UPDATE(OTG_ADD_DROP_PIXEL_CNTL,
+ OTG3_DROP_PIXEL, 1);
+ break;
+ default:
+ ASSERT(0);
+ }
+}
+
+void dccg42_enable_global_fgcg(struct dccg *dccg, bool value)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ if (dccg->ctx->dc->debug.disable_clock_gate)
+ value = false;
+ REG_UPDATE(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, !value);
+}
+
+void dccg42_set_physymclk(
+ struct dccg *dccg,
+ int phy_inst,
+ enum physymclk_clock_source clk_src,
+ bool force_enable)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ switch (phy_inst) {
+ case 0:
+ if (force_enable) {
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYASYMCLK_ROOT_GATE_DISABLE, 1);
+ REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
+ PHYASYMCLK_EN, 1,
+ PHYASYMCLK_SRC_SEL, clk_src);
+ } else {
+ REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL,
+ PHYASYMCLK_EN, 0,
+ PHYASYMCLK_SRC_SEL, 0);
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYASYMCLK_ROOT_GATE_DISABLE,
+ dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1);
+ }
+ break;
+ case 1:
+ if (force_enable) {
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYBSYMCLK_ROOT_GATE_DISABLE, 1);
+ REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
+ PHYBSYMCLK_EN, 1,
+ PHYBSYMCLK_SRC_SEL, clk_src);
+ } else {
+ REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL,
+ PHYBSYMCLK_EN, 0,
+ PHYBSYMCLK_SRC_SEL, 0);
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYBSYMCLK_ROOT_GATE_DISABLE,
+ dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1);
+ }
+ break;
+ case 2:
+ if (force_enable) {
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYCSYMCLK_ROOT_GATE_DISABLE, 1);
+ REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
+ PHYCSYMCLK_EN, 1,
+ PHYCSYMCLK_SRC_SEL, clk_src);
+ } else {
+ REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL,
+ PHYCSYMCLK_EN, 0,
+ PHYCSYMCLK_SRC_SEL, 0);
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYCSYMCLK_ROOT_GATE_DISABLE,
+ dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1);
+ }
+ break;
+ case 3:
+ if (force_enable) {
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYDSYMCLK_ROOT_GATE_DISABLE, 1);
+ REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
+ PHYDSYMCLK_EN, 1,
+ PHYDSYMCLK_SRC_SEL, clk_src);
+ } else {
+ REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL,
+ PHYDSYMCLK_EN, 0,
+ PHYDSYMCLK_SRC_SEL, 0);
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYDSYMCLK_ROOT_GATE_DISABLE,
+ dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1);
+ }
+ break;
+ case 4:
+ if (force_enable) {
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYESYMCLK_ROOT_GATE_DISABLE, 1);
+ REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
+ PHYESYMCLK_EN, 1,
+ PHYESYMCLK_SRC_SEL, clk_src);
+ } else {
+ REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL,
+ PHYESYMCLK_EN, 0,
+ PHYESYMCLK_SRC_SEL, 0);
+ REG_UPDATE(DCCG_GATE_DISABLE_CNTL2,
+ PHYESYMCLK_ROOT_GATE_DISABLE,
+ dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk ? 0 : 1);
+ }
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+}
+
+void dccg42_set_pixel_rate_div(
+ struct dccg *dccg,
+ uint32_t otg_inst,
+ enum pixel_rate_div tmds_div,
+ enum pixel_rate_div unused)
+{
+ (void)unused;
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+ uint32_t cur_tmds_div = PIXEL_RATE_DIV_NA;
+ uint32_t dp_dto_int;
+ uint32_t reg_val;
+
+ // only 2 and 4 are valid on dcn401
+ if (tmds_div != PIXEL_RATE_DIV_BY_2 && tmds_div != PIXEL_RATE_DIV_BY_4) {
+ return;
+ }
+
+ dccg401_get_pixel_rate_div(dccg, otg_inst, &cur_tmds_div, &dp_dto_int);
+ if (tmds_div == cur_tmds_div)
+ return;
+
+ // encode enum to register value
+ reg_val = tmds_div == PIXEL_RATE_DIV_BY_4 ? 1 : 0;
+
+ switch (otg_inst) {
+ case 0:
+ REG_UPDATE(OTG_PIXEL_RATE_DIV,
+ OTG0_TMDS_PIXEL_RATE_DIV, reg_val);
+ break;
+ case 1:
+ REG_UPDATE(OTG_PIXEL_RATE_DIV,
+ OTG1_TMDS_PIXEL_RATE_DIV, reg_val);
+ break;
+ case 2:
+ REG_UPDATE(OTG_PIXEL_RATE_DIV,
+ OTG2_TMDS_PIXEL_RATE_DIV, reg_val);
+ break;
+ case 3:
+ REG_UPDATE(OTG_PIXEL_RATE_DIV,
+ OTG3_TMDS_PIXEL_RATE_DIV, reg_val);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ return;
+ }
+}
+
+void dccg42_trigger_dio_fifo_resync(struct dccg *dccg)
+{
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ REG_UPDATE(DISPCLK_FREQ_CHANGE_CNTL, RESYNC_FIFO_LEVEL_ADJUST_EN, 1);
+ REG_UPDATE(DISPCLK_FREQ_CHANGE_CNTL, RESYNC_FIFO_LEVEL_ADJUST_EN, 0);
+ REG_WAIT(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_FREQ_RAMP_DONE, 1, 50, 2000);
+}
+
+static void dccg42_init(struct dccg *dccg)
+{
+ int otg_inst;
+ struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+ /* Set HPO stream encoder to use refclk to avoid case where PHY is
+ * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which
+ * will cause DCN to hang.
+ */
+ for (otg_inst = 0; otg_inst < 4; otg_inst++)
+ dccg35_disable_symclk32_se(dccg, otg_inst);
+
+ if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) {
+ dccg401_disable_symclk32_le(dccg, 0);
+ dccg401_disable_symclk32_le(dccg, 1);
+ dccg401_disable_symclk32_le(dccg, 2);
+ dccg401_disable_symclk32_le(dccg, 3);
+ }
+
+ if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) {
+ dccg401_disable_dpstreamclk(dccg, 0);
+ dccg401_disable_dpstreamclk(dccg, 1);
+ dccg401_disable_dpstreamclk(dccg, 2);
+ dccg401_disable_dpstreamclk(dccg, 3);
+ }
+ if (!dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) {
+ REG_UPDATE_5(DCCG_GATE_DISABLE_CNTL2,
+ PHYASYMCLK_ROOT_GATE_DISABLE, 1,
+ PHYBSYMCLK_ROOT_GATE_DISABLE, 1,
+ PHYCSYMCLK_ROOT_GATE_DISABLE, 1,
+ PHYDSYMCLK_ROOT_GATE_DISABLE, 1,
+ PHYESYMCLK_ROOT_GATE_DISABLE, 1);
+ }
+}
+
+
+static const struct dccg_funcs dccg42_funcs = {
+ .update_dpp_dto = dccg35_update_dpp_dto,
+ .dpp_root_clock_control = dccg35_dpp_root_clock_control,
+ .get_dccg_ref_freq = dccg401_get_dccg_ref_freq,
+ .dccg_init = dccg42_init,
+ .set_dpstreamclk = dccg401_set_dpstreamclk,
+ /* Redundant with above^ */
+ /* .set_dpstreamclk_root_clock_gating = dccg35_set_dpstreamclk_root_clock_gating, */
+ .enable_symclk32_se = dccg31_enable_symclk32_se,
+ .disable_symclk32_se = dccg35_disable_symclk32_se,
+ .enable_symclk32_le = dccg401_enable_symclk32_le,
+ .disable_symclk32_le = dccg401_disable_symclk32_le,
+ .set_symclk32_le_root_clock_gating = dccg31_set_symclk32_le_root_clock_gating,
+ .set_physymclk = dccg42_set_physymclk,
+ .set_dtbclk_dto = NULL,
+ .set_dto_dscclk = dccg401_set_dto_dscclk,
+ .set_ref_dscclk = dccg401_set_ref_dscclk,
+ .set_valid_pixel_rate = NULL,
+ .set_fifo_errdet_ovr_en = dccg2_set_fifo_errdet_ovr_en,
+ .set_audio_dtbclk_dto = NULL,
+ .otg_add_pixel = dccg42_otg_add_pixel,
+ .otg_drop_pixel = dccg42_otg_drop_pixel,
+ .disable_dsc = dccg35_disable_dscclk,
+ .enable_dsc = dccg35_enable_dscclk,
+ .set_pixel_rate_div = dccg42_set_pixel_rate_div,
+ .get_pixel_rate_div = dccg401_get_pixel_rate_div,
+ .trigger_dio_fifo_resync = dccg42_trigger_dio_fifo_resync,
+ .set_dp_dto = dccg401_set_dp_dto,
+ .enable_symclk_se = dccg35_enable_symclk_se,
+ .disable_symclk_se = dccg35_disable_symclk_se,
+ .set_dtbclk_p_src = dccg401_set_dtbclk_p_src,
+ .dccg_root_gate_disable_control = dccg35_root_gate_disable_control,
+ .dccg_read_reg_state = dccg31_read_reg_state,
+ .dccg_enable_global_fgcg = dccg42_enable_global_fgcg,
+};
+
+struct dccg *dccg42_create(
+ struct dc_context *ctx,
+ const struct dccg_registers *regs,
+ const struct dccg_shift *dccg_shift,
+ const struct dccg_mask *dccg_mask)
+{
+ struct dcn_dccg *dccg_dcn = kzalloc(sizeof(*dccg_dcn), GFP_KERNEL);
+ struct dccg *base;
+
+ if (dccg_dcn == NULL) {
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+
+ base = &dccg_dcn->base;
+ base->ctx = ctx;
+ base->funcs = &dccg42_funcs;
+
+ dccg_dcn->regs = regs;
+ dccg_dcn->dccg_shift = dccg_shift;
+ dccg_dcn->dccg_mask = dccg_mask;
+
+ return &dccg_dcn->base;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h
new file mode 100644
index 000000000000..2076565b1caa
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn42/dcn42_dccg.h
@@ -0,0 +1,273 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2024-2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DCN42_DCCG_H__
+#define __DCN42_DCCG_H__
+
+#include "dcn401/dcn401_dccg.h"
+
+#define DCCG_MASK_SH_LIST_DCN42_COMMON(mask_sh) \
+ DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 0, mask_sh),\
+ DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 1, mask_sh),\
+ DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 2, mask_sh),\
+ DCCG_SFI(DPPCLK_DTO_CTRL, DTO_DB_EN, DPPCLK, 3, mask_sh),\
+ DCCG_SF(DPPCLK_CTRL, DPPCLK0_EN, mask_sh),\
+ DCCG_SF(DPPCLK_CTRL, DPPCLK1_EN, mask_sh),\
+ DCCG_SF(DPPCLK_CTRL, DPPCLK2_EN, mask_sh),\
+ DCCG_SF(DPPCLK_CTRL, DPPCLK3_EN, mask_sh),\
+ DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_STEP_DELAY, mask_sh),\
+ DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_STEP_SIZE, mask_sh),\
+ DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_FREQ_RAMP_DONE, mask_sh),\
+ DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_MAX_ERRDET_CYCLES, mask_sh),\
+ DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_RESET, mask_sh),\
+ DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_STATE, mask_sh),\
+ DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DCCG_FIFO_ERRDET_OVR_EN, mask_sh),\
+ DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, DISPCLK_CHG_FWD_CORR_DISABLE, mask_sh),\
+ DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_PHASE, mask_sh),\
+ DCCG_SF(DPPCLK0_DTO_PARAM, DPPCLK0_DTO_MODULO, mask_sh),\
+ DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_EN, mask_sh),\
+ DCCG_SF(HDMICHARCLK0_CLOCK_CNTL, HDMICHARCLK0_SRC_SEL, mask_sh),\
+ DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK0_EN, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK0_SRC_SEL, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK1_SRC_SEL, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK2_SRC_SEL, mask_sh),\
+ DCCG_SF(DPSTREAMCLK_CNTL, DPSTREAMCLK3_SRC_SEL, mask_sh),\
+ DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_EN, mask_sh),\
+ DCCG_SF(HDMISTREAMCLK_CNTL, HDMISTREAMCLK0_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE2_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE0_EN, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE1_EN, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE2_EN, mask_sh),\
+ DCCG_SF(SYMCLK32_SE_CNTL, SYMCLK32_SE3_EN, mask_sh),\
+ DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE0_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE1_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE2_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE3_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE0_EN, mask_sh),\
+ DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE1_EN, mask_sh),\
+ DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE2_EN, mask_sh),\
+ DCCG_SF(SYMCLK32_LE_CNTL, SYMCLK32_LE3_EN, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 0, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 1, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 2, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 3, mask_sh),\
+ DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG0_ADD_PIXEL, mask_sh),\
+ DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG1_ADD_PIXEL, mask_sh),\
+ DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG2_ADD_PIXEL, mask_sh),\
+ DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG3_ADD_PIXEL, mask_sh),\
+ DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG0_DROP_PIXEL, mask_sh),\
+ DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG1_DROP_PIXEL, mask_sh),\
+ DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG2_DROP_PIXEL, mask_sh),\
+ DCCG_SF(OTG_ADD_DROP_PIXEL_CNTL, OTG3_DROP_PIXEL, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, OTG0_TMDS_PIXEL_RATE_DIV, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO0_INT, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, OTG1_TMDS_PIXEL_RATE_DIV, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO1_INT, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, OTG2_TMDS_PIXEL_RATE_DIV, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO2_INT, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, OTG3_TMDS_PIXEL_RATE_DIV, mask_sh),\
+ DCCG_SF(OTG_PIXEL_RATE_DIV, DPDTO3_INT, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P0_SRC_SEL, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P0_EN, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P1_SRC_SEL, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P1_EN, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P2_SRC_SEL, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P2_EN, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_SRC_SEL, mask_sh),\
+ DCCG_SF(DTBCLK_P_CNTL, DTBCLK_P3_EN, mask_sh),\
+ DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\
+ DCCG_SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\
+ DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh),\
+ DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, mask_sh),\
+ DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\
+ DCCG_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_MODE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GLOBAL_FGCG_REP_CNTL, DCCG_GLOBAL_FGCG_REP_DIS, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 0, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 1, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 2, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, DP_DTO, ENABLE, 3, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 0, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 1, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 2, mask_sh),\
+ DCCG_SFII(OTG, PIXEL_RATE_CNTL, PIPE, DTO_SRC_SEL, 3, mask_sh),\
+ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK0_EN, mask_sh),\
+ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK1_EN, mask_sh),\
+ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK2_EN, mask_sh),\
+ DCCG_SF(DSCCLK_DTO_CTRL, DSCCLK3_EN, mask_sh),\
+ DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_PHASE, mask_sh),\
+ DCCG_SF(DSCCLK0_DTO_PARAM, DSCCLK0_DTO_MODULO, mask_sh),\
+ DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_PHASE, mask_sh),\
+ DCCG_SF(DSCCLK1_DTO_PARAM, DSCCLK1_DTO_MODULO, mask_sh),\
+ DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_PHASE, mask_sh),\
+ DCCG_SF(DSCCLK2_DTO_PARAM, DSCCLK2_DTO_MODULO, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL, DISPCLK_DCCG_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, HDMICHARCLK0_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, HDMISTREAMCLK0_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKA_FE_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKB_FE_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKC_FE_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKD_FE_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKA_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKB_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKC_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, SYMCLKD_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE0_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE1_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE2_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_SE3_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE0_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE1_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE2_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_ROOT_LE3_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE0_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE1_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE2_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_SE3_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE0_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE1_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE2_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL3, SYMCLK32_LE3_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL4, HDMICHARCLK0_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYA_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYB_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYC_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYD_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK0_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK1_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK2_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK0_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK1_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK2_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DPPCLK3_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL6, HDMISTREAMCLK0_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, mask_sh),\
+ DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, mask_sh),\
+ DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, mask_sh),\
+ DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, mask_sh),\
+ DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, mask_sh),\
+ DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, mask_sh),\
+ DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, mask_sh),\
+ DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, mask_sh),\
+ DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_SRC_SEL, mask_sh)
+
+#define DCCG_MASK_SH_LIST_DCN42(mask_sh) \
+ DCCG_MASK_SH_LIST_DCN42_COMMON(mask_sh),\
+ DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_EN, mask_sh),\
+ DCCG_SF(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_SRC_SEL, mask_sh),\
+ DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_PHASE, mask_sh),\
+ DCCG_SF(HDMISTREAMCLK0_DTO_PARAM, HDMISTREAMCLK0_DTO_MODULO, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_PHASE, mask_sh),\
+ DCCG_SF(DSCCLK3_DTO_PARAM, DSCCLK3_DTO_MODULO, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL4, PHYE_REFCLK_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(DCCG_GATE_DISABLE_CNTL6, DSCCLK3_ROOT_GATE_DISABLE, mask_sh),\
+ DCCG_SF(SYMCLKA_CLOCK_ENABLE, SYMCLKA_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_SRC_SEL, mask_sh),\
+ DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, mask_sh),\
+ DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_EN, mask_sh),\
+ DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_SRC_SEL, mask_sh),\
+ DCCG_SF(DISPCLK_FREQ_CHANGE_CNTL, RESYNC_FIFO_LEVEL_ADJUST_EN, mask_sh)
+
+
+void dccg42_otg_add_pixel(struct dccg *dccg,
+ uint32_t otg_inst);
+
+void dccg42_otg_drop_pixel(struct dccg *dccg,
+ uint32_t otg_inst);
+void dccg42_enable_global_fgcg(struct dccg *dccg, bool value);
+
+void dccg42_set_physymclk(
+ struct dccg *dccg,
+ int phy_inst,
+ enum physymclk_clock_source clk_src,
+ bool force_enable);
+
+void dccg42_set_pixel_rate_div(
+ struct dccg *dccg,
+ uint32_t otg_inst,
+ enum pixel_rate_div tmds_div,
+ enum pixel_rate_div unused);
+
+void dccg42_trigger_dio_fifo_resync(struct dccg *dccg);
+
+struct dccg *dccg42_create(
+ struct dc_context *ctx,
+ const struct dccg_registers *regs,
+ const struct dccg_shift *dccg_shift,
+ const struct dccg_mask *dccg_mask);
+
+#endif //__DCN42_DCCG_H__
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
index 41169b42534c..469b4b8f88a3 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c
@@ -57,6 +57,7 @@
static bool dce_abm_set_pipe(struct abm *abm, uint32_t controller_id, uint32_t panel_inst)
{
+ (void)panel_inst;
struct dce_abm *abm_dce = TO_DCE_ABM(abm);
uint32_t rampingBoundary = 0xFFFF;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
index 3d819fc5654c..1e9ab5ff3a31 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-16 Advanced Micro Devices, Inc.
+ * Copyright 2012-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -300,6 +300,64 @@
ABM_SF(ABM0_DC_ABM1_HG_BIN_57_64_SHIFT_INDEX, \
ABM1_HG_BIN_57_64_SHIFT_INDEX, mask_sh)
+#define ABM_MASK_SH_LIST_DCN42(mask_sh) \
+ ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
+ ABM1_HG_NUM_OF_BINS_SEL, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
+ ABM1_HG_VMAX_SEL, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_HG_MISC_CTRL, \
+ ABM1_HG_BIN_BITWIDTH_SIZE_SEL, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
+ ABM1_IPCSC_COEFF_SEL_R, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
+ ABM1_IPCSC_COEFF_SEL_G, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_IPCSC_COEFF_SEL, \
+ ABM1_IPCSC_COEFF_SEL_B, mask_sh), \
+ ABM_SF(ABM0_BL1_PWM_CURRENT_ABM_LEVEL, \
+ BL1_PWM_CURRENT_ABM_LEVEL, mask_sh), \
+ ABM_SF(ABM0_BL1_PWM_TARGET_ABM_LEVEL, \
+ BL1_PWM_TARGET_ABM_LEVEL, mask_sh), \
+ ABM_SF(ABM0_BL1_PWM_USER_LEVEL, \
+ BL1_PWM_USER_LEVEL, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
+ ABM1_LS_MIN_PIXEL_VALUE_THRES, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, \
+ ABM1_LS_MAX_PIXEL_VALUE_THRES, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
+ ABM1_HG_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
+ ABM1_LS_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_HGLS_REG_READ_PROGRESS, \
+ ABM1_BL_REG_READ_MISSED_FRAME_CLEAR, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_ACE_OFFSET_SLOPE_DATA, \
+ ABM1_ACE_SLOPE_DATA, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_ACE_OFFSET_SLOPE_DATA, \
+ ABM1_ACE_OFFSET_DATA, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
+ ABM1_ACE_OFFSET_SLOPE_INDEX, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
+ ABM1_ACE_IGNORE_MASTER_LOCK_EN, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
+ ABM1_ACE_READBACK_DB_REG_VALUE_EN, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
+ ABM1_ACE_DBUF_REG_UPDATE_PENDING, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_ACE_PWL_CNTL, \
+ ABM1_ACE_LOCK, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_HG_RESULT_DATA, \
+ ABM1_HG_RESULT_DATA, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_HG_RESULT_INDEX, \
+ ABM1_HG_RESULT_INDEX, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_HG_BIN_33_40_SHIFT_INDEX, \
+ ABM1_HG_BIN_33_40_SHIFT_INDEX, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_HG_BIN_33_64_SHIFT_FLAG, \
+ ABM1_HG_BIN_33_64_SHIFT_FLAG, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_HG_BIN_41_48_SHIFT_INDEX, \
+ ABM1_HG_BIN_41_48_SHIFT_INDEX, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_HG_BIN_49_56_SHIFT_INDEX, \
+ ABM1_HG_BIN_49_56_SHIFT_INDEX, mask_sh), \
+ ABM_SF(ABM0_DC_ABM1_HG_BIN_57_64_SHIFT_INDEX, \
+ ABM1_HG_BIN_57_64_SHIFT_INDEX, mask_sh)
+
#define ABM_REG_FIELD_LIST(type) \
type ABM1_HG_NUM_OF_BINS_SEL; \
type ABM1_HG_VMAX_SEL; \
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
index d18490cd0f1e..77df61bfaf27 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
@@ -350,6 +350,7 @@ static uint32_t calculate_required_audio_bw_in_symbols(
uint32_t av_stream_map_lane_count,
uint32_t audio_sdp_overhead)
{
+ (void)channel_count;
/* DP spec recommends between 1.05 to 1.1 safety margin to prevent sample under-run */
struct fixed31_32 audio_sdp_margin = dc_fixpt_from_fraction(110, 100);
struct fixed31_32 horizontal_line_freq_khz = dc_fixpt_from_fraction(
@@ -1027,6 +1028,7 @@ static void get_azalia_clock_info_hdmi(
uint32_t actual_pixel_clock_100Hz,
struct azalia_clock_info *azalia_clock_info)
{
+ (void)crtc_pixel_clock_100hz;
/* audio_dto_phase= 24 * 10,000;
* 24MHz in [100Hz] units */
azalia_clock_info->audio_dto_phase =
@@ -1043,6 +1045,7 @@ static void get_azalia_clock_info_dp(
const struct audio_pll_info *pll_info,
struct azalia_clock_info *azalia_clock_info)
{
+ (void)requested_pixel_clock_100Hz;
/* Reported dpDtoSourceClockInkhz value for
* DCE8 already adjusted for SS, do not need any
* adjustment here anymore
@@ -1150,98 +1153,6 @@ void dce_aud_wall_dto_setup(
}
}
-#if defined(CONFIG_DRM_AMD_DC_SI)
-static void dce60_aud_wall_dto_setup(
- struct audio *audio,
- enum signal_type signal,
- const struct audio_crtc_info *crtc_info,
- const struct audio_pll_info *pll_info)
-{
- struct dce_audio *aud = DCE_AUD(audio);
-
- struct azalia_clock_info clock_info = { 0 };
-
- if (dc_is_hdmi_signal(signal)) {
- uint32_t src_sel;
-
- /*DTO0 Programming goal:
- -generate 24MHz, 128*Fs from 24MHz
- -use DTO0 when an active HDMI port is connected
- (optionally a DP is connected) */
-
- /* calculate DTO settings */
- get_azalia_clock_info_hdmi(
- crtc_info->requested_pixel_clock_100Hz,
- crtc_info->calculated_pixel_clock_100Hz,
- &clock_info);
-
- DC_LOG_HW_AUDIO("\n%s:Input::requested_pixel_clock_100Hz = %d"\
- "calculated_pixel_clock_100Hz =%d\n"\
- "audio_dto_module = %d audio_dto_phase =%d \n\n", __func__,\
- crtc_info->requested_pixel_clock_100Hz,\
- crtc_info->calculated_pixel_clock_100Hz,\
- clock_info.audio_dto_module,\
- clock_info.audio_dto_phase);
-
- /* On TN/SI, Program DTO source select and DTO select before
- programming DTO modulo and DTO phase. These bits must be
- programmed first, otherwise there will be no HDMI audio at boot
- up. This is a HW sequence change (different from old ASICs).
- Caution when changing this programming sequence.
-
- HDMI enabled, using DTO0
- program master CRTC for DTO0 */
- src_sel = pll_info->dto_source - DTO_SOURCE_ID0;
- REG_UPDATE_2(DCCG_AUDIO_DTO_SOURCE,
- DCCG_AUDIO_DTO0_SOURCE_SEL, src_sel,
- DCCG_AUDIO_DTO_SEL, 0);
-
- /* module */
- REG_UPDATE(DCCG_AUDIO_DTO0_MODULE,
- DCCG_AUDIO_DTO0_MODULE, clock_info.audio_dto_module);
-
- /* phase */
- REG_UPDATE(DCCG_AUDIO_DTO0_PHASE,
- DCCG_AUDIO_DTO0_PHASE, clock_info.audio_dto_phase);
- } else {
- /*DTO1 Programming goal:
- -generate 24MHz, 128*Fs from 24MHz (DCE6 does not support 512*Fs)
- -default is to used DTO1, and switch to DTO0 when an audio
- master HDMI port is connected
- -use as default for DP
-
- calculate DTO settings */
- get_azalia_clock_info_dp(
- crtc_info->requested_pixel_clock_100Hz,
- pll_info,
- &clock_info);
-
- /* Program DTO select before programming DTO modulo and DTO
- phase. default to use DTO1 */
-
- REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
- DCCG_AUDIO_DTO_SEL, 1);
-
- /* DCCG_AUDIO_DTO2_USE_512FBR_DTO, 1)
- * Cannot select 512fs for DP
- *
- * DCE6 has no DCCG_AUDIO_DTO2_USE_512FBR_DTO mask
- */
-
- /* module */
- REG_UPDATE(DCCG_AUDIO_DTO1_MODULE,
- DCCG_AUDIO_DTO1_MODULE, clock_info.audio_dto_module);
-
- /* phase */
- REG_UPDATE(DCCG_AUDIO_DTO1_PHASE,
- DCCG_AUDIO_DTO1_PHASE, clock_info.audio_dto_phase);
-
- /* DCE6 has no DCCG_AUDIO_DTO2_USE_512FBR_DTO mask in DCCG_AUDIO_DTO_SOURCE reg */
-
- }
-}
-#endif
-
static bool dce_aud_endpoint_valid(struct audio *audio)
{
uint32_t value;
@@ -1303,18 +1214,6 @@ static const struct audio_funcs funcs = {
.destroy = dce_aud_destroy,
};
-#if defined(CONFIG_DRM_AMD_DC_SI)
-static const struct audio_funcs dce60_funcs = {
- .endpoint_valid = dce_aud_endpoint_valid,
- .hw_init = dce_aud_hw_init,
- .wall_dto_setup = dce60_aud_wall_dto_setup,
- .az_enable = dce_aud_az_enable,
- .az_disable = dce_aud_az_disable,
- .az_configure = dce_aud_az_configure,
- .destroy = dce_aud_destroy,
-};
-#endif
-
void dce_aud_destroy(struct audio **audio)
{
struct dce_audio *aud = DCE_AUD(*audio);
@@ -1347,30 +1246,3 @@ struct audio *dce_audio_create(
audio->masks = masks;
return &audio->base;
}
-
-#if defined(CONFIG_DRM_AMD_DC_SI)
-struct audio *dce60_audio_create(
- struct dc_context *ctx,
- unsigned int inst,
- const struct dce_audio_registers *reg,
- const struct dce_audio_shift *shifts,
- const struct dce_audio_mask *masks
- )
-{
- struct dce_audio *audio = kzalloc_obj(*audio);
-
- if (audio == NULL) {
- ASSERT_CRITICAL(audio);
- return NULL;
- }
-
- audio->base.ctx = ctx;
- audio->base.inst = inst;
- audio->base.funcs = &dce60_funcs;
-
- audio->regs = reg;
- audio->shifts = shifts;
- audio->masks = masks;
- return &audio->base;
-}
-#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h
index 1b7b8b079af4..3f1d161a0045 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.h
@@ -151,15 +151,6 @@ struct audio *dce_audio_create(
const struct dce_audio_shift *shifts,
const struct dce_audio_mask *masks);
-#if defined(CONFIG_DRM_AMD_DC_SI)
-struct audio *dce60_audio_create(
- struct dc_context *ctx,
- unsigned int inst,
- const struct dce_audio_registers *reg,
- const struct dce_audio_shift *shifts,
- const struct dce_audio_mask *masks);
-#endif
-
void dce_aud_destroy(struct audio **audio);
void dce_aud_hw_init(struct audio *audio);
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c
deleted file mode 100644
index dca025b5ff1f..000000000000
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
- * Copyright 2012-16 Advanced Micro Devices, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: AMD
- *
- */
-
-#include <linux/slab.h>
-
-#include "dce_clk_mgr.h"
-
-#include "reg_helper.h"
-#include "dmcu.h"
-#include "core_types.h"
-#include "dal_asic_id.h"
-
-#define TO_DCE_CLK_MGR(clocks)\
- container_of(clocks, struct dce_clk_mgr, base)
-
-#define REG(reg) \
- (clk_mgr_dce->regs->reg)
-
-#undef FN
-#define FN(reg_name, field_name) \
- clk_mgr_dce->clk_mgr_shift->field_name, clk_mgr_dce->clk_mgr_mask->field_name
-
-#define CTX \
- clk_mgr_dce->base.ctx
-#define DC_LOGGER \
- clk_mgr->ctx->logger
-
-/* Max clock values for each state indexed by "enum clocks_state": */
-static const struct state_dependent_clocks dce80_max_clks_by_state[] = {
-/* ClocksStateInvalid - should not be used */
-{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
-/* ClocksStateUltraLow - not expected to be used for DCE 8.0 */
-{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
-/* ClocksStateLow */
-{ .display_clk_khz = 352000, .pixel_clk_khz = 330000},
-/* ClocksStateNominal */
-{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 },
-/* ClocksStatePerformance */
-{ .display_clk_khz = 600000, .pixel_clk_khz = 400000 } };
-
-static const struct state_dependent_clocks dce110_max_clks_by_state[] = {
-/*ClocksStateInvalid - should not be used*/
-{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
-/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/
-{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 },
-/*ClocksStateLow*/
-{ .display_clk_khz = 352000, .pixel_clk_khz = 330000 },
-/*ClocksStateNominal*/
-{ .display_clk_khz = 467000, .pixel_clk_khz = 400000 },
-/*ClocksStatePerformance*/
-{ .display_clk_khz = 643000, .pixel_clk_khz = 400000 } };
-
-static const struct state_dependent_clocks dce112_max_clks_by_state[] = {
-/*ClocksStateInvalid - should not be used*/
-{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
-/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/
-{ .display_clk_khz = 389189, .pixel_clk_khz = 346672 },
-/*ClocksStateLow*/
-{ .display_clk_khz = 459000, .pixel_clk_khz = 400000 },
-/*ClocksStateNominal*/
-{ .display_clk_khz = 667000, .pixel_clk_khz = 600000 },
-/*ClocksStatePerformance*/
-{ .display_clk_khz = 1132000, .pixel_clk_khz = 600000 } };
-
-static const struct state_dependent_clocks dce120_max_clks_by_state[] = {
-/*ClocksStateInvalid - should not be used*/
-{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
-/*ClocksStateUltraLow - currently by HW design team not supposed to be used*/
-{ .display_clk_khz = 0, .pixel_clk_khz = 0 },
-/*ClocksStateLow*/
-{ .display_clk_khz = 460000, .pixel_clk_khz = 400000 },
-/*ClocksStateNominal*/
-{ .display_clk_khz = 670000, .pixel_clk_khz = 600000 },
-/*ClocksStatePerformance*/
-{ .display_clk_khz = 1133000, .pixel_clk_khz = 600000 } };
-
-int dentist_get_divider_from_did(int did)
-{
- if (did < DENTIST_BASE_DID_1)
- did = DENTIST_BASE_DID_1;
- if (did > DENTIST_MAX_DID)
- did = DENTIST_MAX_DID;
-
- if (did < DENTIST_BASE_DID_2) {
- return DENTIST_DIVIDER_RANGE_1_START + DENTIST_DIVIDER_RANGE_1_STEP
- * (did - DENTIST_BASE_DID_1);
- } else if (did < DENTIST_BASE_DID_3) {
- return DENTIST_DIVIDER_RANGE_2_START + DENTIST_DIVIDER_RANGE_2_STEP
- * (did - DENTIST_BASE_DID_2);
- } else if (did < DENTIST_BASE_DID_4) {
- return DENTIST_DIVIDER_RANGE_3_START + DENTIST_DIVIDER_RANGE_3_STEP
- * (did - DENTIST_BASE_DID_3);
- } else {
- return DENTIST_DIVIDER_RANGE_4_START + DENTIST_DIVIDER_RANGE_4_STEP
- * (did - DENTIST_BASE_DID_4);
- }
-}
-
-/* SW will adjust DP REF Clock average value for all purposes
- * (DP DTO / DP Audio DTO and DP GTC)
- if clock is spread for all cases:
- -if SS enabled on DP Ref clock and HW de-spreading enabled with SW
- calculations for DS_INCR/DS_MODULO (this is planned to be default case)
- -if SS enabled on DP Ref clock and HW de-spreading enabled with HW
- calculations (not planned to be used, but average clock should still
- be valid)
- -if SS enabled on DP Ref clock and HW de-spreading disabled
- (should not be case with CIK) then SW should program all rates
- generated according to average value (case as with previous ASICs)
- */
-static int clk_mgr_adjust_dp_ref_freq_for_ss(struct dce_clk_mgr *clk_mgr_dce, int dp_ref_clk_khz)
-{
- if (clk_mgr_dce->ss_on_dprefclk && clk_mgr_dce->dprefclk_ss_divider != 0) {
- struct fixed31_32 ss_percentage = dc_fixpt_div_int(
- dc_fixpt_from_fraction(clk_mgr_dce->dprefclk_ss_percentage,
- clk_mgr_dce->dprefclk_ss_divider), 200);
- struct fixed31_32 adj_dp_ref_clk_khz;
-
- ss_percentage = dc_fixpt_sub(dc_fixpt_one, ss_percentage);
- adj_dp_ref_clk_khz = dc_fixpt_mul_int(ss_percentage, dp_ref_clk_khz);
- dp_ref_clk_khz = dc_fixpt_floor(adj_dp_ref_clk_khz);
- }
- return dp_ref_clk_khz;
-}
-
-static int dce_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr)
-{
- struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
- int dprefclk_wdivider;
- int dprefclk_src_sel;
- int dp_ref_clk_khz = 600000;
- int target_div;
-
- /* ASSERT DP Reference Clock source is from DFS*/
- REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel);
- ASSERT(dprefclk_src_sel == 0);
-
- /* Read the mmDENTIST_DISPCLK_CNTL to get the currently
- * programmed DID DENTIST_DPREFCLK_WDIVIDER*/
- REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider);
-
- /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/
- target_div = dentist_get_divider_from_did(dprefclk_wdivider);
-
- /* Calculate the current DFS clock, in kHz.*/
- dp_ref_clk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR
- * clk_mgr_dce->dentist_vco_freq_khz) / target_div;
-
- return clk_mgr_adjust_dp_ref_freq_for_ss(clk_mgr_dce, dp_ref_clk_khz);
-}
-
-int dce12_get_dp_ref_freq_khz(struct clk_mgr *clk_mgr)
-{
- struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
-
- return clk_mgr_adjust_dp_ref_freq_for_ss(clk_mgr_dce, clk_mgr_dce->dprefclk_khz);
-}
-
-/* unit: in_khz before mode set, get pixel clock from context. ASIC register
- * may not be programmed yet
- */
-static uint32_t get_max_pixel_clock_for_all_paths(struct dc_state *context)
-{
- uint32_t max_pix_clk = 0;
- int i;
-
- for (i = 0; i < MAX_PIPES; i++) {
- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-
- if (pipe_ctx->stream == NULL)
- continue;
-
- /* do not check under lay */
- if (pipe_ctx->top_pipe)
- continue;
-
- if (pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10 > max_pix_clk)
- max_pix_clk = pipe_ctx->stream_res.pix_clk_params.requested_pix_clk_100hz / 10;
-
- /* raise clock state for HBR3/2 if required. Confirmed with HW DCE/DPCS
- * logic for HBR3 still needs Nominal (0.8V) on VDDC rail
- */
- if (dc_is_dp_signal(pipe_ctx->stream->signal) &&
- pipe_ctx->stream_res.pix_clk_params.requested_sym_clk > max_pix_clk)
- max_pix_clk = pipe_ctx->stream_res.pix_clk_params.requested_sym_clk;
- }
-
- return max_pix_clk;
-}
-
-static enum dm_pp_clocks_state dce_get_required_clocks_state(
- struct clk_mgr *clk_mgr,
- struct dc_state *context)
-{
- struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
- int i;
- enum dm_pp_clocks_state low_req_clk;
- int max_pix_clk = get_max_pixel_clock_for_all_paths(context);
-
- /* Iterate from highest supported to lowest valid state, and update
- * lowest RequiredState with the lowest state that satisfies
- * all required clocks
- */
- for (i = clk_mgr_dce->max_clks_state; i >= DM_PP_CLOCKS_STATE_ULTRA_LOW; i--)
- if (context->bw_ctx.bw.dce.dispclk_khz >
- clk_mgr_dce->max_clks_by_state[i].display_clk_khz
- || max_pix_clk >
- clk_mgr_dce->max_clks_by_state[i].pixel_clk_khz)
- break;
-
- low_req_clk = i + 1;
- if (low_req_clk > clk_mgr_dce->max_clks_state) {
- /* set max clock state for high phyclock, invalid on exceeding display clock */
- if (clk_mgr_dce->max_clks_by_state[clk_mgr_dce->max_clks_state].display_clk_khz
- < context->bw_ctx.bw.dce.dispclk_khz)
- low_req_clk = DM_PP_CLOCKS_STATE_INVALID;
- else
- low_req_clk = clk_mgr_dce->max_clks_state;
- }
-
- return low_req_clk;
-}
-
-static int dce_set_clock(
- struct clk_mgr *clk_mgr,
- int requested_clk_khz)
-{
- struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
- struct bp_pixel_clock_parameters pxl_clk_params = { 0 };
- struct dc_bios *bp = clk_mgr->ctx->dc_bios;
- int actual_clock = requested_clk_khz;
- struct dmcu *dmcu = clk_mgr_dce->base.ctx->dc->res_pool->dmcu;
-
- /* Make sure requested clock isn't lower than minimum threshold*/
- if (requested_clk_khz > 0)
- requested_clk_khz = max(requested_clk_khz,
- clk_mgr_dce->dentist_vco_freq_khz / 64);
-
- /* Prepare to program display clock*/
- pxl_clk_params.target_pixel_clock_100hz = requested_clk_khz * 10;
- pxl_clk_params.pll_id = CLOCK_SOURCE_ID_DFS;
-
- if (clk_mgr_dce->dfs_bypass_active)
- pxl_clk_params.flags.SET_DISPCLK_DFS_BYPASS = true;
-
- bp->funcs->program_display_engine_pll(bp, &pxl_clk_params);
-
- if (clk_mgr_dce->dfs_bypass_active) {
- /* Cache the fixed display clock*/
- clk_mgr_dce->dfs_bypass_disp_clk =
- pxl_clk_params.dfs_bypass_display_clock;
- actual_clock = pxl_clk_params.dfs_bypass_display_clock;
- }
-
- /* from power down, we need mark the clock state as ClocksStateNominal
- * from HWReset, so when resume we will call pplib voltage regulator.*/
- if (requested_clk_khz == 0)
- clk_mgr_dce->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL;
-
- if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu))
- dmcu->funcs->set_psr_wait_loop(dmcu, actual_clock / 1000 / 7);
-
- return actual_clock;
-}
-
-int dce112_set_clock(struct clk_mgr *clk_mgr, int requested_clk_khz)
-{
- struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
- struct bp_set_dce_clock_parameters dce_clk_params;
- struct dc_bios *bp = clk_mgr->ctx->dc_bios;
- struct dc *core_dc = clk_mgr->ctx->dc;
- struct dmcu *dmcu = core_dc->res_pool->dmcu;
- int actual_clock = requested_clk_khz;
- /* Prepare to program display clock*/
- memset(&dce_clk_params, 0, sizeof(dce_clk_params));
-
- /* Make sure requested clock isn't lower than minimum threshold*/
- if (requested_clk_khz > 0)
- requested_clk_khz = max(requested_clk_khz,
- clk_mgr_dce->dentist_vco_freq_khz / 62);
-
- dce_clk_params.target_clock_frequency = requested_clk_khz;
- dce_clk_params.pll_id = CLOCK_SOURCE_ID_DFS;
- dce_clk_params.clock_type = DCECLOCK_TYPE_DISPLAY_CLOCK;
-
- bp->funcs->set_dce_clock(bp, &dce_clk_params);
- actual_clock = dce_clk_params.target_clock_frequency;
-
- /* from power down, we need mark the clock state as ClocksStateNominal
- * from HWReset, so when resume we will call pplib voltage regulator.*/
- if (requested_clk_khz == 0)
- clk_mgr_dce->cur_min_clks_state = DM_PP_CLOCKS_STATE_NOMINAL;
-
- /*Program DP ref Clock*/
- /*VBIOS will determine DPREFCLK frequency, so we don't set it*/
- dce_clk_params.target_clock_frequency = 0;
- dce_clk_params.clock_type = DCECLOCK_TYPE_DPREFCLK;
-
- if (!((clk_mgr->ctx->asic_id.chip_family == FAMILY_AI) &&
- ASICREV_IS_VEGA20_P(clk_mgr->ctx->asic_id.hw_internal_rev)))
- dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK =
- (dce_clk_params.pll_id ==
- CLOCK_SOURCE_COMBO_DISPLAY_PLL0);
- else
- dce_clk_params.flags.USE_GENLOCK_AS_SOURCE_FOR_DPREFCLK = false;
-
- bp->funcs->set_dce_clock(bp, &dce_clk_params);
-
- if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) {
- if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) {
- if (clk_mgr_dce->dfs_bypass_disp_clk != actual_clock)
- dmcu->funcs->set_psr_wait_loop(dmcu,
- actual_clock / 1000 / 7);
- }
- }
-
- clk_mgr_dce->dfs_bypass_disp_clk = actual_clock;
- return actual_clock;
-}
-
-static void dce_clock_read_integrated_info(struct dce_clk_mgr *clk_mgr_dce)
-{
- struct dc_debug_options *debug = &clk_mgr_dce->base.ctx->dc->debug;
- struct dc_bios *bp = clk_mgr_dce->base.ctx->dc_bios;
- struct integrated_info info = { { { 0 } } };
- struct dc_firmware_info fw_info = { { 0 } };
- int i;
-
- if (bp->integrated_info)
- info = *bp->integrated_info;
-
- clk_mgr_dce->dentist_vco_freq_khz = info.dentist_vco_freq;
- if (clk_mgr_dce->dentist_vco_freq_khz == 0) {
- bp->funcs->get_firmware_info(bp, &fw_info);
- clk_mgr_dce->dentist_vco_freq_khz =
- fw_info.smu_gpu_pll_output_freq;
- if (clk_mgr_dce->dentist_vco_freq_khz == 0)
- clk_mgr_dce->dentist_vco_freq_khz = 3600000;
- }
-
- /*update the maximum display clock for each power state*/
- for (i = 0; i < NUMBER_OF_DISP_CLK_VOLTAGE; ++i) {
- enum dm_pp_clocks_state clk_state = DM_PP_CLOCKS_STATE_INVALID;
-
- switch (i) {
- case 0:
- clk_state = DM_PP_CLOCKS_STATE_ULTRA_LOW;
- break;
-
- case 1:
- clk_state = DM_PP_CLOCKS_STATE_LOW;
- break;
-
- case 2:
- clk_state = DM_PP_CLOCKS_STATE_NOMINAL;
- break;
-
- case 3:
- clk_state = DM_PP_CLOCKS_STATE_PERFORMANCE;
- break;
-
- default:
- clk_state = DM_PP_CLOCKS_STATE_INVALID;
- break;
- }
-
- /*Do not allow bad VBIOS/SBIOS to override with invalid values,
- * check for > 100MHz*/
- if (info.disp_clk_voltage[i].max_supported_clk >= 100000)
- clk_mgr_dce->max_clks_by_state[clk_state].display_clk_khz =
- info.disp_clk_voltage[i].max_supported_clk;
- }
-
- if (!debug->disable_dfs_bypass && bp->integrated_info)
- if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE)
- clk_mgr_dce->dfs_bypass_enabled = true;
-}
-
-void dce_clock_read_ss_info(struct dce_clk_mgr *clk_mgr_dce)
-{
- struct dc_bios *bp = clk_mgr_dce->base.ctx->dc_bios;
- int ss_info_num = bp->funcs->get_ss_entry_number(
- bp, AS_SIGNAL_TYPE_GPU_PLL);
-
- if (ss_info_num) {
- struct spread_spectrum_info info = { { 0 } };
- enum bp_result result = bp->funcs->get_spread_spectrum_info(
- bp, AS_SIGNAL_TYPE_GPU_PLL, 0, &info);
-
- /* Based on VBIOS, VBIOS will keep entry for GPU PLL SS
- * even if SS not enabled and in that case
- * SSInfo.spreadSpectrumPercentage !=0 would be sign
- * that SS is enabled
- */
- if (result == BP_RESULT_OK &&
- info.spread_spectrum_percentage != 0) {
- clk_mgr_dce->ss_on_dprefclk = true;
- clk_mgr_dce->dprefclk_ss_divider = info.spread_percentage_divider;
-
- if (info.type.CENTER_MODE == 0) {
- /* TODO: Currently for DP Reference clock we
- * need only SS percentage for
- * downspread */
- clk_mgr_dce->dprefclk_ss_percentage =
- info.spread_spectrum_percentage;
- }
-
- return;
- }
-
- result = bp->funcs->get_spread_spectrum_info(
- bp, AS_SIGNAL_TYPE_DISPLAY_PORT, 0, &info);
-
- /* Based on VBIOS, VBIOS will keep entry for DPREFCLK SS
- * even if SS not enabled and in that case
- * SSInfo.spreadSpectrumPercentage !=0 would be sign
- * that SS is enabled
- */
- if (result == BP_RESULT_OK &&
- info.spread_spectrum_percentage != 0) {
- clk_mgr_dce->ss_on_dprefclk = true;
- clk_mgr_dce->dprefclk_ss_divider = info.spread_percentage_divider;
-
- if (info.type.CENTER_MODE == 0) {
- /* Currently for DP Reference clock we
- * need only SS percentage for
- * downspread */
- clk_mgr_dce->dprefclk_ss_percentage =
- info.spread_spectrum_percentage;
- }
- if (clk_mgr_dce->base.ctx->dc->debug.ignore_dpref_ss)
- clk_mgr_dce->dprefclk_ss_percentage = 0;
- }
- }
-}
-
-/**
- * dce121_clock_patch_xgmi_ss_info() - Save XGMI spread spectrum info
- * @clk_mgr: clock manager base structure
- *
- * Reads from VBIOS the XGMI spread spectrum info and saves it within
- * the dce clock manager. This operation will overwrite the existing dprefclk
- * SS values if the vBIOS query succeeds. Otherwise, it does nothing. It also
- * sets the ->xgmi_enabled flag.
- */
-void dce121_clock_patch_xgmi_ss_info(struct clk_mgr *clk_mgr)
-{
- struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
- enum bp_result result;
- struct spread_spectrum_info info = { { 0 } };
- struct dc_bios *bp = clk_mgr_dce->base.ctx->dc_bios;
-
- clk_mgr_dce->xgmi_enabled = false;
-
- result = bp->funcs->get_spread_spectrum_info(bp, AS_SIGNAL_TYPE_XGMI,
- 0, &info);
- if (result == BP_RESULT_OK && info.spread_spectrum_percentage != 0) {
- clk_mgr_dce->xgmi_enabled = true;
- clk_mgr_dce->ss_on_dprefclk = true;
- clk_mgr_dce->dprefclk_ss_divider =
- info.spread_percentage_divider;
-
- if (info.type.CENTER_MODE == 0) {
- /* Currently for DP Reference clock we
- * need only SS percentage for
- * downspread */
- clk_mgr_dce->dprefclk_ss_percentage =
- info.spread_spectrum_percentage;
- }
- }
-}
-
-void dce110_fill_display_configs(
- const struct dc_state *context,
- struct dm_pp_display_configuration *pp_display_cfg)
-{
- int j;
- int num_cfgs = 0;
-
- for (j = 0; j < context->stream_count; j++) {
- int k;
-
- const struct dc_stream_state *stream = context->streams[j];
- struct dm_pp_single_disp_config *cfg =
- &pp_display_cfg->disp_configs[num_cfgs];
- const struct pipe_ctx *pipe_ctx = NULL;
-
- for (k = 0; k < MAX_PIPES; k++)
- if (stream == context->res_ctx.pipe_ctx[k].stream) {
- pipe_ctx = &context->res_ctx.pipe_ctx[k];
- break;
- }
-
- ASSERT(pipe_ctx != NULL);
-
- /* only notify active stream */
- if (stream->dpms_off)
- continue;
-
- num_cfgs++;
- cfg->signal = pipe_ctx->stream->signal;
- cfg->pipe_idx = pipe_ctx->stream_res.tg->inst;
- cfg->src_height = stream->src.height;
- cfg->src_width = stream->src.width;
- cfg->ddi_channel_mapping =
- stream->link->ddi_channel_mapping.raw;
- cfg->transmitter =
- stream->link->link_enc->transmitter;
- cfg->link_settings.lane_count =
- stream->link->cur_link_settings.lane_count;
- cfg->link_settings.link_rate =
- stream->link->cur_link_settings.link_rate;
- cfg->link_settings.link_spread =
- stream->link->cur_link_settings.link_spread;
- cfg->sym_clock = stream->phy_pix_clk;
- /* Round v_refresh*/
- cfg->v_refresh = stream->timing.pix_clk_100hz * 100;
- cfg->v_refresh /= stream->timing.h_total;
- cfg->v_refresh = (cfg->v_refresh + stream->timing.v_total / 2)
- / stream->timing.v_total;
- }
-
- pp_display_cfg->display_count = num_cfgs;
-}
-
-static uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context)
-{
- uint8_t j;
- uint32_t min_vertical_blank_time = -1;
-
- for (j = 0; j < context->stream_count; j++) {
- struct dc_stream_state *stream = context->streams[j];
- uint32_t vertical_blank_in_pixels = 0;
- uint32_t vertical_blank_time = 0;
-
- vertical_blank_in_pixels = stream->timing.h_total *
- (stream->timing.v_total
- - stream->timing.v_addressable);
-
- vertical_blank_time = vertical_blank_in_pixels
- * 10000 / stream->timing.pix_clk_100hz;
-
- if (min_vertical_blank_time > vertical_blank_time)
- min_vertical_blank_time = vertical_blank_time;
- }
-
- return min_vertical_blank_time;
-}
-
-static int determine_sclk_from_bounding_box(
- const struct dc *dc,
- int required_sclk)
-{
- int i;
-
- /*
- * Some asics do not give us sclk levels, so we just report the actual
- * required sclk
- */
- if (dc->sclk_lvls.num_levels == 0)
- return required_sclk;
-
- for (i = 0; i < dc->sclk_lvls.num_levels; i++) {
- if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk)
- return dc->sclk_lvls.clocks_in_khz[i];
- }
- /*
- * even maximum level could not satisfy requirement, this
- * is unexpected at this stage, should have been caught at
- * validation time
- */
- ASSERT(0);
- return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1];
-}
-
-static void dce_pplib_apply_display_requirements(
- struct dc *dc,
- struct dc_state *context)
-{
- struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
-
- pp_display_cfg->avail_mclk_switch_time_us = dce110_get_min_vblank_time_us(context);
-
- dce110_fill_display_configs(context, pp_display_cfg);
-
- if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0)
- dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
-}
-
-static void dce11_pplib_apply_display_requirements(
- struct dc *dc,
- struct dc_state *context)
-{
- struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
-
- pp_display_cfg->all_displays_in_sync =
- context->bw_ctx.bw.dce.all_displays_in_sync;
- pp_display_cfg->nb_pstate_switch_disable =
- context->bw_ctx.bw.dce.nbp_state_change_enable == false;
- pp_display_cfg->cpu_cc6_disable =
- context->bw_ctx.bw.dce.cpuc_state_change_enable == false;
- pp_display_cfg->cpu_pstate_disable =
- context->bw_ctx.bw.dce.cpup_state_change_enable == false;
- pp_display_cfg->cpu_pstate_separation_time =
- context->bw_ctx.bw.dce.blackout_recovery_time_us;
-
- pp_display_cfg->min_memory_clock_khz = context->bw_ctx.bw.dce.yclk_khz
- / MEMORY_TYPE_MULTIPLIER_CZ;
-
- pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box(
- dc,
- context->bw_ctx.bw.dce.sclk_khz);
-
- /*
- * As workaround for >4x4K lightup set dcfclock to min_engine_clock value.
- * This is not required for less than 5 displays,
- * thus don't request decfclk in dc to avoid impact
- * on power saving.
- *
- */
- pp_display_cfg->min_dcfclock_khz = (context->stream_count > 4) ?
- pp_display_cfg->min_engine_clock_khz : 0;
-
- pp_display_cfg->min_engine_clock_deep_sleep_khz
- = context->bw_ctx.bw.dce.sclk_deep_sleep_khz;
-
- pp_display_cfg->avail_mclk_switch_time_us =
- dce110_get_min_vblank_time_us(context);
- /* TODO: dce11.2*/
- pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0;
-
- pp_display_cfg->disp_clk_khz = dc->res_pool->clk_mgr->clks.dispclk_khz;
-
- dce110_fill_display_configs(context, pp_display_cfg);
-
- /* TODO: is this still applicable?*/
- if (pp_display_cfg->display_count == 1) {
- const struct dc_crtc_timing *timing =
- &context->streams[0]->timing;
-
- pp_display_cfg->crtc_index =
- pp_display_cfg->disp_configs[0].pipe_idx;
- pp_display_cfg->line_time_in_us = timing->h_total * 10000 / timing->pix_clk_100hz;
- }
-
- if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0)
- dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
-}
-
-static void dce_update_clocks(struct clk_mgr *clk_mgr,
- struct dc_state *context,
- bool safe_to_lower)
-{
- struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
- struct dm_pp_power_level_change_request level_change_req;
- int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz;
-
- /*TODO: W/A for dal3 linux, investigate why this works */
- if (!clk_mgr_dce->dfs_bypass_active)
- patched_disp_clk = patched_disp_clk * 115 / 100;
-
- level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context);
- /* get max clock state from PPLIB */
- if ((level_change_req.power_level < clk_mgr_dce->cur_min_clks_state && safe_to_lower)
- || level_change_req.power_level > clk_mgr_dce->cur_min_clks_state) {
- if (dm_pp_apply_power_level_change_request(clk_mgr->ctx, &level_change_req))
- clk_mgr_dce->cur_min_clks_state = level_change_req.power_level;
- }
-
- if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) {
- patched_disp_clk = dce_set_clock(clk_mgr, patched_disp_clk);
- clk_mgr->clks.dispclk_khz = patched_disp_clk;
- }
- dce_pplib_apply_display_requirements(clk_mgr->ctx->dc, context);
-}
-
-static void dce11_update_clocks(struct clk_mgr *clk_mgr,
- struct dc_state *context,
- bool safe_to_lower)
-{
- struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
- struct dm_pp_power_level_change_request level_change_req;
- int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz;
-
- /*TODO: W/A for dal3 linux, investigate why this works */
- if (!clk_mgr_dce->dfs_bypass_active)
- patched_disp_clk = patched_disp_clk * 115 / 100;
-
- level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context);
- /* get max clock state from PPLIB */
- if ((level_change_req.power_level < clk_mgr_dce->cur_min_clks_state && safe_to_lower)
- || level_change_req.power_level > clk_mgr_dce->cur_min_clks_state) {
- if (dm_pp_apply_power_level_change_request(clk_mgr->ctx, &level_change_req))
- clk_mgr_dce->cur_min_clks_state = level_change_req.power_level;
- }
-
- if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) {
- context->bw_ctx.bw.dce.dispclk_khz = dce_set_clock(clk_mgr, patched_disp_clk);
- clk_mgr->clks.dispclk_khz = patched_disp_clk;
- }
- dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context);
-}
-
-static void dce112_update_clocks(struct clk_mgr *clk_mgr,
- struct dc_state *context,
- bool safe_to_lower)
-{
- struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
- struct dm_pp_power_level_change_request level_change_req;
- int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz;
-
- /*TODO: W/A for dal3 linux, investigate why this works */
- if (!clk_mgr_dce->dfs_bypass_active)
- patched_disp_clk = patched_disp_clk * 115 / 100;
-
- level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context);
- /* get max clock state from PPLIB */
- if ((level_change_req.power_level < clk_mgr_dce->cur_min_clks_state && safe_to_lower)
- || level_change_req.power_level > clk_mgr_dce->cur_min_clks_state) {
- if (dm_pp_apply_power_level_change_request(clk_mgr->ctx, &level_change_req))
- clk_mgr_dce->cur_min_clks_state = level_change_req.power_level;
- }
-
- if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) {
- patched_disp_clk = dce112_set_clock(clk_mgr, patched_disp_clk);
- clk_mgr->clks.dispclk_khz = patched_disp_clk;
- }
- dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context);
-}
-
-static void dce12_update_clocks(struct clk_mgr *clk_mgr,
- struct dc_state *context,
- bool safe_to_lower)
-{
- struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
- struct dm_pp_clock_for_voltage_req clock_voltage_req = {0};
- int max_pix_clk = get_max_pixel_clock_for_all_paths(context);
- int patched_disp_clk = context->bw_ctx.bw.dce.dispclk_khz;
-
- /*TODO: W/A for dal3 linux, investigate why this works */
- if (!clk_mgr_dce->dfs_bypass_active)
- patched_disp_clk = patched_disp_clk * 115 / 100;
-
- if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) {
- clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DISPLAY_CLK;
- /*
- * When xGMI is enabled, the display clk needs to be adjusted
- * with the WAFL link's SS percentage.
- */
- if (clk_mgr_dce->xgmi_enabled)
- patched_disp_clk = clk_mgr_adjust_dp_ref_freq_for_ss(
- clk_mgr_dce, patched_disp_clk);
- clock_voltage_req.clocks_in_khz = patched_disp_clk;
- clk_mgr->clks.dispclk_khz = dce112_set_clock(clk_mgr, patched_disp_clk);
-
- dm_pp_apply_clock_for_voltage_request(clk_mgr->ctx, &clock_voltage_req);
- }
-
- if (should_set_clock(safe_to_lower, max_pix_clk, clk_mgr->clks.phyclk_khz)) {
- clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DISPLAYPHYCLK;
- clock_voltage_req.clocks_in_khz = max_pix_clk;
- clk_mgr->clks.phyclk_khz = max_pix_clk;
-
- dm_pp_apply_clock_for_voltage_request(clk_mgr->ctx, &clock_voltage_req);
- }
- dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context);
-}
-
-static const struct clk_mgr_funcs dce120_funcs = {
- .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
- .update_clocks = dce12_update_clocks
-};
-
-static const struct clk_mgr_funcs dce112_funcs = {
- .get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz,
- .update_clocks = dce112_update_clocks
-};
-
-static const struct clk_mgr_funcs dce110_funcs = {
- .get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz,
- .update_clocks = dce11_update_clocks,
-};
-
-static const struct clk_mgr_funcs dce_funcs = {
- .get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz,
- .update_clocks = dce_update_clocks
-};
-
-static void dce_clk_mgr_construct(
- struct dce_clk_mgr *clk_mgr_dce,
- struct dc_context *ctx,
- const struct clk_mgr_registers *regs,
- const struct clk_mgr_shift *clk_shift,
- const struct clk_mgr_mask *clk_mask)
-{
- struct clk_mgr *base = &clk_mgr_dce->base;
- struct dm_pp_static_clock_info static_clk_info = {0};
-
- base->ctx = ctx;
- base->funcs = &dce_funcs;
-
- clk_mgr_dce->regs = regs;
- clk_mgr_dce->clk_mgr_shift = clk_shift;
- clk_mgr_dce->clk_mgr_mask = clk_mask;
-
- clk_mgr_dce->dfs_bypass_disp_clk = 0;
-
- clk_mgr_dce->dprefclk_ss_percentage = 0;
- clk_mgr_dce->dprefclk_ss_divider = 1000;
- clk_mgr_dce->ss_on_dprefclk = false;
-
-
- if (dm_pp_get_static_clocks(ctx, &static_clk_info))
- clk_mgr_dce->max_clks_state = static_clk_info.max_clocks_state;
- else
- clk_mgr_dce->max_clks_state = DM_PP_CLOCKS_STATE_NOMINAL;
- clk_mgr_dce->cur_min_clks_state = DM_PP_CLOCKS_STATE_INVALID;
-
- dce_clock_read_integrated_info(clk_mgr_dce);
- dce_clock_read_ss_info(clk_mgr_dce);
-}
-
-struct clk_mgr *dce_clk_mgr_create(
- struct dc_context *ctx,
- const struct clk_mgr_registers *regs,
- const struct clk_mgr_shift *clk_shift,
- const struct clk_mgr_mask *clk_mask)
-{
- struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce);
-
- if (clk_mgr_dce == NULL) {
- BREAK_TO_DEBUGGER();
- return NULL;
- }
-
- memcpy(clk_mgr_dce->max_clks_by_state,
- dce80_max_clks_by_state,
- sizeof(dce80_max_clks_by_state));
-
- dce_clk_mgr_construct(
- clk_mgr_dce, ctx, regs, clk_shift, clk_mask);
-
- return &clk_mgr_dce->base;
-}
-
-struct clk_mgr *dce110_clk_mgr_create(
- struct dc_context *ctx,
- const struct clk_mgr_registers *regs,
- const struct clk_mgr_shift *clk_shift,
- const struct clk_mgr_mask *clk_mask)
-{
- struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce);
-
- if (clk_mgr_dce == NULL) {
- BREAK_TO_DEBUGGER();
- return NULL;
- }
-
- memcpy(clk_mgr_dce->max_clks_by_state,
- dce110_max_clks_by_state,
- sizeof(dce110_max_clks_by_state));
-
- dce_clk_mgr_construct(
- clk_mgr_dce, ctx, regs, clk_shift, clk_mask);
-
- clk_mgr_dce->base.funcs = &dce110_funcs;
-
- return &clk_mgr_dce->base;
-}
-
-struct clk_mgr *dce112_clk_mgr_create(
- struct dc_context *ctx,
- const struct clk_mgr_registers *regs,
- const struct clk_mgr_shift *clk_shift,
- const struct clk_mgr_mask *clk_mask)
-{
- struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce);
-
- if (clk_mgr_dce == NULL) {
- BREAK_TO_DEBUGGER();
- return NULL;
- }
-
- memcpy(clk_mgr_dce->max_clks_by_state,
- dce112_max_clks_by_state,
- sizeof(dce112_max_clks_by_state));
-
- dce_clk_mgr_construct(
- clk_mgr_dce, ctx, regs, clk_shift, clk_mask);
-
- clk_mgr_dce->base.funcs = &dce112_funcs;
-
- return &clk_mgr_dce->base;
-}
-
-struct clk_mgr *dce120_clk_mgr_create(struct dc_context *ctx)
-{
- struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce);
-
- if (clk_mgr_dce == NULL) {
- BREAK_TO_DEBUGGER();
- return NULL;
- }
-
- memcpy(clk_mgr_dce->max_clks_by_state,
- dce120_max_clks_by_state,
- sizeof(dce120_max_clks_by_state));
-
- dce_clk_mgr_construct(
- clk_mgr_dce, ctx, NULL, NULL, NULL);
-
- clk_mgr_dce->dprefclk_khz = 600000;
- clk_mgr_dce->base.funcs = &dce120_funcs;
-
- return &clk_mgr_dce->base;
-}
-
-struct clk_mgr *dce121_clk_mgr_create(struct dc_context *ctx)
-{
- struct dce_clk_mgr *clk_mgr_dce = kzalloc_obj(*clk_mgr_dce);
-
- if (clk_mgr_dce == NULL) {
- BREAK_TO_DEBUGGER();
- return NULL;
- }
-
- memcpy(clk_mgr_dce->max_clks_by_state, dce120_max_clks_by_state,
- sizeof(dce120_max_clks_by_state));
-
- dce_clk_mgr_construct(clk_mgr_dce, ctx, NULL, NULL, NULL);
-
- clk_mgr_dce->dprefclk_khz = 625000;
- clk_mgr_dce->base.funcs = &dce120_funcs;
-
- return &clk_mgr_dce->base;
-}
-
-void dce_clk_mgr_destroy(struct clk_mgr **clk_mgr)
-{
- struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(*clk_mgr);
-
- kfree(clk_mgr_dce);
- *clk_mgr = NULL;
-}
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 5722be965422..34e54fdb9d13 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
@@ -539,6 +539,7 @@ static void dce112_get_pix_clk_dividers_helper (
struct pll_settings *pll_settings,
struct pixel_clk_params *pix_clk_params)
{
+ (void)clk_src;
uint32_t actual_pixel_clock_100hz;
actual_pixel_clock_100hz = pix_clk_params->requested_pix_clk_100hz;
@@ -610,7 +611,7 @@ static uint32_t dce112_get_pix_clk_dividers(
|| pix_clk_params->requested_pix_clk_100hz == 0) {
DC_LOG_ERROR(
"%s: Invalid parameters!!\n", __func__);
- return -1;
+ return (uint32_t)-1;
}
memset(pll_settings, 0, sizeof(*pll_settings));
@@ -621,7 +622,7 @@ static uint32_t dce112_get_pix_clk_dividers(
pll_settings->calculated_pix_clk_100hz = clk_src->ext_clk_khz * 10;
pll_settings->actual_pix_clk_100hz =
pix_clk_params->requested_pix_clk_100hz;
- return -1;
+ return (uint32_t)-1;
}
dce112_get_pix_clk_dividers_helper(clk_src,
@@ -847,6 +848,7 @@ static bool dce110_program_pix_clk(
enum dp_link_encoding encoding,
struct pll_settings *pll_settings)
{
+ (void)encoding;
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
struct bp_pixel_clock_parameters bp_pc_params = {0};
@@ -921,6 +923,7 @@ static bool dce112_program_pix_clk(
enum dp_link_encoding encoding,
struct pll_settings *pll_settings)
{
+ (void)encoding;
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
struct bp_pixel_clock_parameters bp_pc_params = {0};
@@ -1070,6 +1073,7 @@ static bool dcn401_program_pix_clk(
enum dp_link_encoding encoding,
struct pll_settings *pll_settings)
{
+ (void)encoding;
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
const struct pixel_rate_range_table_entry *e =
@@ -1376,7 +1380,7 @@ static uint32_t dcn3_get_pix_clk_dividers(
|| pix_clk_params->requested_pix_clk_100hz == 0) {
DC_LOG_ERROR(
"%s: Invalid parameters!!\n", __func__);
- return -1;
+ return UINT_MAX;
}
memset(pll_settings, 0, sizeof(*pll_settings));
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
index e871b72e43ef..25ebd8a52ae4 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
@@ -71,6 +71,7 @@ static const uint32_t abm_gain_stepsize = 0x0060;
static bool dce_dmcu_init(struct dmcu *dmcu)
{
+ (void)dmcu;
// Do nothing
return true;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c
index f5cd2392fc5f..f5261e8d7678 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c.c
@@ -31,6 +31,7 @@ bool dce_i2c_oem_device_present(
size_t slave_address
)
{
+ (void)pool;
struct dc *dc = ddc->ctx->dc;
struct dc_bios *dcb = dc->ctx->dc_bios;
struct graphics_object_id id = {0};
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
index 365dd2e37aea..fe239a96121e 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.c
@@ -69,6 +69,7 @@ static enum i2c_channel_operation_result get_channel_status(
struct dce_i2c_hw *dce_i2c_hw,
uint8_t *returned_bytes)
{
+ (void)returned_bytes;
uint32_t i2c_sw_status = 0;
uint32_t value =
REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
@@ -631,6 +632,7 @@ bool dce_i2c_submit_command_hw(
struct i2c_command *cmd,
struct dce_i2c_hw *dce_i2c_hw)
{
+ (void)ddc;
uint8_t index_of_payload = 0;
bool result;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c
index 2d73b94c515c..52e05b9185f1 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_sw.c
@@ -67,6 +67,7 @@ static void release_engine_dce_sw(
struct resource_pool *pool,
struct dce_i2c_sw *dce_i2c_sw)
{
+ (void)pool;
dal_ddc_close(dce_i2c_sw->ddc);
dce_i2c_sw->ddc = NULL;
}
@@ -76,6 +77,7 @@ static bool wait_for_scl_high_sw(
struct ddc *ddc,
uint16_t clock_delay_div_4)
{
+ (void)ctx;
uint32_t scl_retry = 0;
uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
@@ -469,6 +471,7 @@ bool dce_i2c_submit_command_sw(
struct i2c_command *cmd,
struct dce_i2c_sw *dce_i2c_sw)
{
+ (void)ddc;
uint8_t index_of_payload = 0;
bool result;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c
index 34bff9aef66c..ee55ec21d270 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_ipp.c
@@ -43,6 +43,7 @@ static void dce_ipp_cursor_set_position(
const struct dc_cursor_position *position,
const struct dc_cursor_mi_param *param)
{
+ (void)param;
struct dce_ipp *ipp_dce = TO_DCE_IPP(ipp);
/* lock cursor registers */
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
index 2ba3d3a3aac5..5f40ae9e3120 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
@@ -122,6 +122,33 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = {
.program_hpd_filter = dce110_program_hpd_filter,
};
+static const struct link_encoder_funcs dce110_lnk_enc_funcs_no_hpd = {
+ .validate_output_with_stream =
+ dce110_link_encoder_validate_output_with_stream,
+ .hw_init = dce110_link_encoder_hw_init,
+ .setup = dce110_link_encoder_setup,
+ .enable_tmds_output = dce110_link_encoder_enable_tmds_output,
+ .enable_dp_output = dce110_link_encoder_enable_dp_output,
+ .enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output,
+ .enable_lvds_output = dce110_link_encoder_enable_lvds_output,
+ .enable_analog_output = dce110_link_encoder_enable_analog_output,
+ .disable_output = dce110_link_encoder_disable_output,
+ .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,
+ .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern,
+ .update_mst_stream_allocation_table =
+ dce110_link_encoder_update_mst_stream_allocation_table,
+ .psr_program_dp_dphy_fast_training =
+ dce110_psr_program_dp_dphy_fast_training,
+ .psr_program_secondary_packet = dce110_psr_program_secondary_packet,
+ .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,
+ .is_dig_enabled = dce110_is_dig_enabled,
+ .destroy = dce110_link_encoder_destroy,
+ .get_max_link_cap = dce110_link_encoder_get_max_link_cap,
+ .get_dig_frontend = dce110_get_dig_frontend,
+ .get_hpd_state = dce110_get_hpd_state,
+ .program_hpd_filter = dce110_program_hpd_filter,
+};
+
static enum bp_result link_transmitter_control(
struct dce110_link_encoder *enc110,
struct bp_transmitter_control *cntl)
@@ -820,6 +847,7 @@ bool dce110_link_encoder_validate_dp_output(
const struct dce110_link_encoder *enc110,
const struct dc_crtc_timing *crtc_timing)
{
+ (void)enc110;
if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
return false;
@@ -865,7 +893,10 @@ void dce110_link_encoder_construct(
const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;
enum bp_result result = BP_RESULT_OK;
- enc110->base.funcs = &dce110_lnk_enc_funcs;
+ if (hpd_regs)
+ enc110->base.funcs = &dce110_lnk_enc_funcs;
+ else
+ enc110->base.funcs = &dce110_lnk_enc_funcs_no_hpd;
enc110->base.ctx = init_data->ctx;
enc110->base.id = init_data->encoder;
enc110->base.analog_id = init_data->analog_encoder;
@@ -1855,6 +1886,33 @@ static const struct link_encoder_funcs dce60_lnk_enc_funcs = {
.program_hpd_filter = dce110_program_hpd_filter,
};
+static const struct link_encoder_funcs dce60_lnk_enc_funcs_no_hpd = {
+ .validate_output_with_stream =
+ dce110_link_encoder_validate_output_with_stream,
+ .hw_init = dce110_link_encoder_hw_init,
+ .setup = dce110_link_encoder_setup,
+ .enable_tmds_output = dce110_link_encoder_enable_tmds_output,
+ .enable_dp_output = dce60_link_encoder_enable_dp_output,
+ .enable_dp_mst_output = dce60_link_encoder_enable_dp_mst_output,
+ .enable_lvds_output = dce110_link_encoder_enable_lvds_output,
+ .enable_analog_output = dce110_link_encoder_enable_analog_output,
+ .disable_output = dce110_link_encoder_disable_output,
+ .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings,
+ .dp_set_phy_pattern = dce60_link_encoder_dp_set_phy_pattern,
+ .update_mst_stream_allocation_table =
+ dce110_link_encoder_update_mst_stream_allocation_table,
+ .psr_program_dp_dphy_fast_training =
+ dce110_psr_program_dp_dphy_fast_training,
+ .psr_program_secondary_packet = dce110_psr_program_secondary_packet,
+ .connect_dig_be_to_fe = dce110_link_encoder_connect_dig_be_to_fe,
+ .is_dig_enabled = dce110_is_dig_enabled,
+ .destroy = dce110_link_encoder_destroy,
+ .get_max_link_cap = dce110_link_encoder_get_max_link_cap,
+ .get_dig_frontend = dce110_get_dig_frontend,
+ .get_hpd_state = dce110_get_hpd_state,
+ .program_hpd_filter = dce110_program_hpd_filter,
+};
+
void dce60_link_encoder_construct(
struct dce110_link_encoder *enc110,
const struct encoder_init_data *init_data,
@@ -1867,7 +1925,10 @@ void dce60_link_encoder_construct(
const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;
enum bp_result result = BP_RESULT_OK;
- enc110->base.funcs = &dce60_lnk_enc_funcs;
+ if (hpd_regs)
+ enc110->base.funcs = &dce60_lnk_enc_funcs;
+ else
+ enc110->base.funcs = &dce60_lnk_enc_funcs_no_hpd;
enc110->base.ctx = init_data->ctx;
enc110->base.id = init_data->encoder;
enc110->base.analog_id = init_data->analog_encoder;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c
index 1c2009e38aa1..168c2d0a5eaa 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_mem_input.c
@@ -317,6 +317,7 @@ static void dce_mi_program_display_marks(
struct dce_watermarks urgent,
uint32_t total_dest_line_time_ns)
{
+ (void)stutter_enter;
struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
@@ -370,6 +371,7 @@ static void dce112_mi_program_display_marks(struct mem_input *mi,
struct dce_watermarks urgent,
uint32_t total_dest_line_time_ns)
{
+ (void)stutter_entry;
struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
@@ -656,6 +658,8 @@ static void dce_mi_program_surface_config(
struct dc_plane_dcc_param *dcc,
bool horizontal_mirror)
{
+ (void)dcc;
+ (void)horizontal_mirror;
struct dce_mem_input *dce_mi = TO_DCE_MEM_INPUT(mi);
REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
index f342da5a5e50..61d478cfca6d 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_opp.c
@@ -600,6 +600,7 @@ void dce110_opp_set_dyn_expansion(
enum dc_color_depth color_dpth,
enum signal_type signal)
{
+ (void)color_sp;
struct dce110_opp *opp110 = TO_DCE110_OPP(opp);
REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
index 87c19f17c799..ed407e779c12 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
@@ -271,6 +271,8 @@ static void dce110_stream_encoder_dp_set_stream_attribute(
bool use_vsc_sdp_for_colorimetry,
uint32_t enable_sdp_splitting)
{
+ (void)use_vsc_sdp_for_colorimetry;
+ (void)enable_sdp_splitting;
uint32_t h_active_start;
uint32_t v_active_start;
uint32_t misc0 = 0;
@@ -901,6 +903,7 @@ static void dce110_stream_encoder_dp_blank(
struct dc_link *link,
struct stream_encoder *enc)
{
+ (void)link;
struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
uint32_t reg1 = 0;
uint32_t max_retries = DP_BLANK_MAX_RETRY * 10;
@@ -951,6 +954,7 @@ static void dce110_stream_encoder_dp_unblank(
struct stream_encoder *enc,
const struct encoder_unblank_param *param)
{
+ (void)link;
struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc);
if (param->link_settings.link_rate != LINK_RATE_UNKNOWN) {
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
index 1ab5ae9b5ea5..c1448ae47366 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c
@@ -282,6 +282,7 @@ static void calculate_inits(
const struct scaler_data *data,
struct scl_ratios_inits *inits)
{
+ (void)xfm_dce;
struct fixed31_32 h_init;
struct fixed31_32 v_init;
@@ -1240,6 +1241,7 @@ static void program_color_matrix(
const struct out_csc_color_matrix *tbl_entry,
enum grph_color_adjust_option options)
{
+ (void)options;
{
REG_SET_2(OUTPUT_CSC_C11_C12, 0,
OUTPUT_CSC_C11, tbl_entry->regval[0],
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
index b686d89b79b2..93550c5e4d02 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c
@@ -41,8 +41,7 @@ static unsigned int abm_feature_support(struct abm *abm, unsigned int panel_inst
{
struct dc_context *dc = abm->ctx;
struct dc_link *edp_links[MAX_NUM_EDP];
- int i;
- int edp_num;
+ unsigned int i, edp_num;
unsigned int ret = ABM_FEATURE_NO_SUPPORT;
dc_get_edp_links(dc->dc, edp_links, &edp_num);
@@ -174,6 +173,7 @@ static bool dmub_abm_set_backlight_level_pwm_ex(struct abm *abm,
unsigned int controller_id,
unsigned int panel_inst)
{
+ (void)controller_id;
bool ret = false;
unsigned int feature_support;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c
index a641ae04450c..806b5709c9e7 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_abm_lcd.c
@@ -188,6 +188,7 @@ void dmub_abm_init_config(struct abm *abm,
bool dmub_abm_set_pause(struct abm *abm, bool pause, unsigned int panel_inst, unsigned int stream_inst)
{
+ (void)stream_inst;
union dmub_rb_cmd cmd;
struct dc_context *dc = abm->ctx;
uint8_t panel_mask = 0x01 << panel_inst;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
index 7116fdd4c7ec..52673e2f504c 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.c
@@ -28,6 +28,14 @@
#include "dc_types.h"
#include "core_types.h"
+static bool dmub_hw_lock_has_inbox0_lock(const struct dc *dc)
+{
+ return dc->ctx && dc->ctx->dmub_srv &&
+ dc->hwss.dmub_hw_control_lock &&
+ dc->hwss.dmub_hw_control_lock_fast &&
+ dc->ctx->dmub_srv->dmub->meta_info.feature_bits.bits.inbox0_lock_support;
+}
+
void dmub_hw_lock_mgr_cmd(struct dc_dmub_srv *dmub_srv,
bool lock,
union dmub_hw_lock_flags *hw_locks,
@@ -74,7 +82,7 @@ bool dmub_hw_lock_mgr_does_link_require_lock(const struct dc *dc, const struct d
if (link->psr_settings.psr_version == DC_PSR_VERSION_1) {
struct dc_link *edp_links[MAX_NUM_EDP];
- int edp_num;
+ unsigned int edp_num;
dc_get_edp_links(dc, edp_links, &edp_num);
if (edp_num == 1)
@@ -105,5 +113,13 @@ bool should_use_dmub_inbox1_lock(const struct dc *dc, const struct dc_link *link
if (dc->ctx->dce_version >= DCN_VERSION_4_01)
return false;
+ if (dmub_hw_lock_has_inbox0_lock(dc))
+ return false;
+
return dmub_hw_lock_mgr_does_link_require_lock(dc, link);
}
+
+bool should_use_dmub_inbox0_lock_for_link(const struct dc *dc, const struct dc_link *link)
+{
+ return dmub_hw_lock_has_inbox0_lock(dc) && dmub_hw_lock_mgr_does_link_require_lock(dc, link);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.h b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.h
index 4c80ca8484ad..3e8caa930390 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_hw_lock_mgr.h
@@ -46,7 +46,38 @@ void dmub_hw_lock_mgr_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
* Return: true if the inbox1 lock should be used, false otherwise
*/
bool should_use_dmub_inbox1_lock(const struct dc *dc, const struct dc_link *link);
+
+/**
+ * dmub_hw_lock_mgr_does_link_require_lock() - Returns true if the link has a feature that needs the HW lock.
+ *
+ * @dc: Pointer to DC object
+ * @link: The link to check
+ *
+ * Return: true if the link has a feature that needs the HW lock, false otherwise
+ */
bool dmub_hw_lock_mgr_does_link_require_lock(const struct dc *dc, const struct dc_link *link);
+
+/**
+ * dmub_hw_lock_mgr_does_context_require_lock() - Returns true if the context has any stream that needs the HW lock.
+ *
+ * @dc: Pointer to DC object
+ * @context: The context to check
+ *
+ * Return: true if the context has any stream that needs the HW lock, false otherwise
+ */
bool dmub_hw_lock_mgr_does_context_require_lock(const struct dc *dc, const struct dc_state *context);
+/**
+ * should_use_dmub_inbox0_lock_for_link() - Checks if the inbox0 interlock with DMU should be used.
+ *
+ * Is not functionally equivalent to inbox1 as DMUB will not own programming of the relevant locking
+ * registers.
+ *
+ * @dc: pointer to DC object
+ * @link: optional pointer to the link object to check for enabled link features
+ *
+ * Return: true if the inbox0 lock should be used, false otherwise
+ */
+bool should_use_dmub_inbox0_lock_for_link(const struct dc *dc, const struct dc_link *link);
+
#endif /*_DMUB_HW_LOCK_MGR_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
index 28a218149b8b..0af1b8e0a49e 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
@@ -216,6 +216,7 @@ static void dmub_replay_set_coasting_vtotal(struct dmub_replay *dmub,
uint8_t panel_inst,
uint16_t frame_skip_number)
{
+ (void)panel_inst;
union dmub_rb_cmd cmd;
struct dc_context *dc = dmub->ctx;
struct dmub_rb_cmd_replay_set_coasting_vtotal *pCmd = NULL;
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c
index 2c43c2422638..b265a72eeb70 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_mem_input_v.c
@@ -40,6 +40,7 @@ static void set_flip_control(
struct dce_mem_input *mem_input110,
bool immediate)
{
+ (void)immediate;
uint32_t value = 0;
value = dm_read_reg(
@@ -165,6 +166,7 @@ static void program_tiling(
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
+ (void)pixel_format;
uint32_t value = 0;
set_reg_field_value(value, info->gfx8.num_banks,
@@ -642,6 +644,8 @@ static void dce_mem_input_v_program_surface_config(
struct dc_plane_dcc_param *dcc,
bool horizotal_mirror)
{
+ (void)dcc;
+ (void)horizotal_mirror;
struct dce_mem_input *mem_input110 = TO_DCE_MEM_INPUT(mem_input);
enable(mem_input110);
@@ -927,6 +931,7 @@ static void dce_mem_input_v_program_display_marks(
struct dce_watermarks urgent,
uint32_t total_dest_line_time_ns)
{
+ (void)stutter_enter;
program_urgency_watermark_l(
mem_input->ctx,
urgent,
@@ -970,6 +975,9 @@ static void dce110_allocate_mem_input_v(
uint32_t pix_clk_khz,/* for current stream */
uint32_t total_stream_num)
{
+ (void)h_total;
+ (void)v_total;
+ (void)total_stream_num;
uint32_t addr;
uint32_t value;
uint32_t pix_dur;
@@ -1009,6 +1017,8 @@ static void dce110_free_mem_input_v(
struct mem_input *mi,
uint32_t total_stream_num)
{
+ (void)mi;
+ (void)total_stream_num;
}
static const struct mem_input_funcs dce110_mem_input_v_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c
index e096d2b95ef9..cf63fac82832 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_csc_v.c
@@ -110,6 +110,7 @@ static void program_color_matrix_v(
const struct out_csc_color_matrix *tbl_entry,
enum grph_color_adjust_option options)
{
+ (void)options;
struct dc_context *ctx = xfm_dce->base.ctx;
uint32_t cntl_value = dm_read_reg(ctx, mmCOL_MAN_OUTPUT_CSC_CONTROL);
bool use_set_a = (get_reg_field_value(cntl_value,
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c
index 9b65b77e8823..a4e76db46c9c 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_opp_regamma_v.c
@@ -551,5 +551,7 @@ void dce110_opp_set_regamma_mode_v(
struct transform *xfm,
enum opp_regamma mode)
{
+ (void)xfm;
+ (void)mode;
// TODO: need to implement the function
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
index 61b0807693fb..b015b27cd1c6 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator.c
@@ -66,6 +66,7 @@ static void dce110_timing_generator_apply_front_porch_workaround(
struct timing_generator *tg,
struct dc_crtc_timing *timing)
{
+ (void)tg;
if (timing->flags.INTERLACE == 1) {
if (timing->v_front_porch < 2)
timing->v_front_porch = 2;
@@ -1115,6 +1116,7 @@ bool dce110_timing_generator_validate_timing(
const struct dc_crtc_timing *timing,
enum signal_type signal)
{
+ (void)signal;
uint32_t h_blank;
uint32_t h_back_porch, hsync_offset, h_sync_start;
@@ -1490,6 +1492,7 @@ void dce110_timing_generator_enable_reset_trigger(
struct timing_generator *tg,
int source_tg_inst)
{
+ (void)source_tg_inst;
uint32_t value;
uint32_t rising_edge = 0;
uint32_t falling_edge = 0;
@@ -1959,6 +1962,12 @@ void dce110_tg_program_timing(struct timing_generator *tg,
const enum signal_type signal,
bool use_vbios)
{
+ (void)vready_offset;
+ (void)vstartup_start;
+ (void)vupdate_offset;
+ (void)vupdate_width;
+ (void)pstate_keepout;
+ (void)signal;
if (use_vbios)
dce110_timing_generator_program_timing_generator(tg, timing);
else
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
index 9837dec837ff..ba22c93acd81 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_timing_generator_v.c
@@ -442,6 +442,12 @@ static void dce110_timing_generator_v_program_timing(struct timing_generator *tg
const enum signal_type signal,
bool use_vbios)
{
+ (void)vready_offset;
+ (void)vstartup_start;
+ (void)vupdate_offset;
+ (void)vupdate_width;
+ (void)pstate_keepout;
+ (void)signal;
if (use_vbios)
dce110_timing_generator_program_timing_generator(tg, timing);
else
@@ -621,6 +627,7 @@ static void dce110_timing_generator_v_setup_global_swap_lock(
struct timing_generator *tg,
const struct dcp_gsl_params *gsl_params)
{
+ (void)gsl_params;
DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
return;
}
@@ -629,6 +636,7 @@ static void dce110_timing_generator_v_enable_reset_trigger(
struct timing_generator *tg,
int source_tg_inst)
{
+ (void)source_tg_inst;
DC_LOG_ERROR("Timing Sync not supported on underlay pipe\n");
return;
}
@@ -650,6 +658,7 @@ static void dce110_timing_generator_v_tear_down_global_swap_lock(
static void dce110_timing_generator_v_disable_vga(
struct timing_generator *tg)
{
+ (void)tg;
return;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c
index 28d3b2663cd3..6be18665b1f7 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_transform_v.c
@@ -371,6 +371,9 @@ static void calculate_inits(
struct rect *luma_viewport,
struct rect *chroma_viewport)
{
+ (void)xfm_dce;
+ (void)luma_viewport;
+ (void)chroma_viewport;
inits->h_int_scale_ratio_luma =
dc_fixpt_u2d19(data->ratios.horz) << 5;
inits->v_int_scale_ratio_luma =
@@ -619,6 +622,8 @@ static void dce110_xfmv_set_gamut_remap(
struct transform *xfm,
const struct xfm_grph_csc_adjustment *adjust)
{
+ (void)xfm;
+ (void)adjust;
/* DO NOTHING*/
}
@@ -627,6 +632,7 @@ static void dce110_xfmv_set_pixel_storage_depth(
enum lb_pixel_depth depth,
const struct bit_depth_reduction_params *bit_depth_params)
{
+ (void)bit_depth_params;
struct dce_transform *xfm_dce = TO_DCE_TRANSFORM(xfm);
int pixel_depth = 0;
int expan_mode = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c
index 187f45a7f5e1..fe97d3946cab 100644
--- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c
+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_compressor.c
@@ -284,6 +284,7 @@ static uint32_t align_to_chunks_number_per_line(
struct dce112_compressor *cp110,
uint32_t pixels)
{
+ (void)cp110;
return 256 * ((pixels + 255) / 256);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
index 31c4f44ceaac..70410ef0c291 100644
--- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_timing_generator.c
@@ -304,6 +304,7 @@ static void dce120_timing_generator_enable_reset_trigger(
struct timing_generator *tg,
int source)
{
+ (void)source;
enum trigger_source_select trig_src_select = TRIGGER_SOURCE_SELECT_LOGIC_ZERO;
struct dce110_timing_generator *tg110 = DCE110TG_FROM_TG(tg);
uint32_t rising_edge = 0;
@@ -701,6 +702,12 @@ static void dce120_tg_program_timing(struct timing_generator *tg,
const enum signal_type signal,
bool use_vbios)
{
+ (void)vready_offset;
+ (void)vstartup_start;
+ (void)vupdate_offset;
+ (void)vupdate_width;
+ (void)pstate_keepout;
+ (void)signal;
if (use_vbios)
dce110_timing_generator_program_timing_generator(tg, timing);
else
diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
index 88e7a1fc9a30..53c03364f5d4 100644
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_timing_generator.c
@@ -115,6 +115,12 @@ static void dce80_timing_generator_program_timing(struct timing_generator *tg,
const enum signal_type signal,
bool use_vbios)
{
+ (void)vready_offset;
+ (void)vstartup_start;
+ (void)vupdate_offset;
+ (void)vupdate_width;
+ (void)pstate_keepout;
+ (void)signal;
if (!use_vbios)
program_pix_dur(tg, timing->pix_clk_100hz);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
index dcd2cdfe91eb..c702a30563f9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
@@ -381,10 +381,10 @@ bool cm_helper_translate_curve_to_hw_format(struct dc_context *ctx,
}
for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
- seg_distr[i] = -1;
+ seg_distr[i] = (uint32_t)-1;
for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
- if (seg_distr[k] != -1)
+ if (seg_distr[k] != (uint32_t)-1)
hw_points += (1 << seg_distr[k]);
}
@@ -565,7 +565,7 @@ bool cm_helper_translate_curve_to_degamma_hw_format(
for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
- seg_distr[i] = -1;
+ seg_distr[i] = (uint32_t)-1;
/* 12 segments
* segments are from 2^-12 to 0
*/
@@ -573,7 +573,7 @@ bool cm_helper_translate_curve_to_degamma_hw_format(
seg_distr[i] = 4;
for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
- if (seg_distr[k] != -1)
+ if (seg_distr[k] != (uint32_t)-1)
hw_points += (1 << seg_distr[k]);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c
index 365a3215f6d5..e9efbb49586e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dwb.c
@@ -44,6 +44,7 @@
static bool dwb1_get_caps(struct dwbc *dwbc, struct dwb_caps *caps)
{
+ (void)dwbc;
if (caps) {
caps->adapter_id = 0; /* we only support 1 adapter currently */
caps->hw_version = DCN_VERSION_1_0;
@@ -63,6 +64,7 @@ static bool dwb1_get_caps(struct dwbc *dwbc, struct dwb_caps *caps)
static bool dwb1_enable(struct dwbc *dwbc, struct dc_dwb_params *params)
{
+ (void)params;
struct dcn10_dwbc *dwbc10 = TO_DCN10_DWBC(dwbc);
/* disable first. */
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c
index a0d437f0ce2b..f73c5f42ea68 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb_scl.c
@@ -746,7 +746,7 @@ bool dwb_program_horz_scalar(struct dcn20_dwbc *dwbc20,
src_width, dest_width);
if (dc_fixpt_floor(tmp_h_ratio_luma) == 8)
- h_ratio_luma = -1;
+ h_ratio_luma = (uint32_t)-1;
else
h_ratio_luma = dc_fixpt_u3d19(tmp_h_ratio_luma) << 5;
@@ -824,7 +824,7 @@ bool dwb_program_vert_scalar(struct dcn20_dwbc *dwbc20,
src_height, dest_height);
if (dc_fixpt_floor(tmp_v_ratio_luma) == 8)
- v_ratio_luma = -1;
+ v_ratio_luma = (uint32_t)-1;
else
v_ratio_luma = dc_fixpt_u3d19(tmp_v_ratio_luma) << 5;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
index 227aa8672d17..9dbccf58dde5 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_cm_common.c
@@ -159,10 +159,10 @@ bool cm3_helper_translate_curve_to_hw_format(struct dc_context *ctx,
}
for (i = region_end - region_start; i < MAX_REGIONS_NUMBER ; i++)
- seg_distr[i] = -1;
+ seg_distr[i] = (uint32_t)-1;
for (k = 0; k < MAX_REGIONS_NUMBER; k++) {
- if (seg_distr[k] != -1)
+ if (seg_distr[k] != (uint32_t)-1)
hw_points += (1 << seg_distr[k]);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c
index 05aac3e444b4..4c7e4fe3c680 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c
@@ -77,6 +77,7 @@ static void apg31_se_audio_setup(
unsigned int az_inst,
struct audio_info *audio_info)
{
+ (void)az_inst;
struct dcn31_apg *apg31 = DCN31_APG_FROM_APG(apg);
ASSERT(audio_info);
diff --git a/drivers/gpu/drm/amd/display/dc/dio/Makefile b/drivers/gpu/drm/amd/display/dc/dio/Makefile
index 2f5619078e1f..4832533b9514 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dio/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright 2020 Advanced Micro Devices, Inc.
+# Copyright 2020-2026 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -123,4 +123,13 @@ DIO_DCN401 = dcn401_dio_link_encoder.o dcn401_dio_stream_encoder.o
AMD_DAL_DIO_DCN401 = $(addprefix $(AMDDALPATH)/dc/dio/dcn401/,$(DIO_DCN401))
AMD_DISPLAY_FILES += $(AMD_DAL_DIO_DCN401)
+
+###############################################################################
+# DCN42
+###############################################################################
+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)
endif
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
index d928b4dcf6b8..d913f065ecca 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.c
@@ -249,6 +249,7 @@ void enc1_stream_encoder_dp_set_stream_attribute(
bool use_vsc_sdp_for_colorimetry,
uint32_t enable_sdp_splitting)
{
+ (void)enable_sdp_splitting;
uint32_t h_active_start;
uint32_t v_active_start;
uint32_t misc0 = 0;
@@ -783,6 +784,7 @@ void enc1_stream_encoder_send_immediate_sdp_message(
const uint8_t *custom_sdp_message,
unsigned int sdp_message_size)
{
+ (void)sdp_message_size;
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
uint32_t value = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h
index 54a6a4ebd636..755367506556 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_stream_encoder.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
+ * Copyright 2012-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -190,6 +190,7 @@ struct dcn10_stream_enc_registers {
uint32_t DIG_FE_CLK_CNTL;
uint32_t DIG_FE_EN_CNTL;
uint32_t STREAM_MAPPER_CONTROL;
+ uint32_t DIG_FE_AUDIO_CNTL;
};
@@ -598,6 +599,11 @@ struct dcn10_stream_enc_registers {
type DP_VID_N_INTERVAL;\
type DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE;\
type DP_STEER_FIFO_ENABLE
+
+#define SE_REG_FIELD_LIST_DCN_AUDIO_COMMON(type) \
+ type DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL;\
+ type APG_CLOCK_ENABLE
+
struct dcn10_stream_encoder_shift {
SE_REG_FIELD_LIST_DCN1_0(uint8_t);
uint8_t HDMI_ACP_SEND;
@@ -606,6 +612,7 @@ struct dcn10_stream_encoder_shift {
SE_REG_FIELD_LIST_DCN3_1_COMMON(uint8_t);
SE_REG_FIELD_LIST_DCN3_5_COMMON(uint8_t);
SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t);
+ SE_REG_FIELD_LIST_DCN_AUDIO_COMMON(uint32_t);
};
struct dcn10_stream_encoder_mask {
@@ -616,6 +623,7 @@ struct dcn10_stream_encoder_mask {
SE_REG_FIELD_LIST_DCN3_1_COMMON(uint32_t);
SE_REG_FIELD_LIST_DCN3_5_COMMON(uint32_t);
SE_REG_FIELD_LIST_DCN4_01_COMMON(uint32_t);
+ SE_REG_FIELD_LIST_DCN_AUDIO_COMMON(uint32_t);
};
struct dcn10_stream_encoder {
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c
index 3e85e9c3d2cb..d1fd5462dca5 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn314/dcn314_dio_stream_encoder.c
@@ -394,6 +394,8 @@ void enc314_dp_set_dsc_config(struct stream_encoder *enc,
uint32_t dsc_bytes_per_pixel,
uint32_t dsc_slice_width)
{
+ (void)dsc_bytes_per_pixel;
+ (void)dsc_slice_width;
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
REG_UPDATE(DP_DSC_CNTL, DP_DSC_MODE, dsc_mode == OPTC_DSC_DISABLED ? 0 : 1);
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c
index 3523d1cdc1a3..edafa3808455 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn32/dcn32_dio_stream_encoder.c
@@ -356,6 +356,8 @@ static void enc32_dp_set_dsc_config(struct stream_encoder *enc,
uint32_t dsc_bytes_per_pixel,
uint32_t dsc_slice_width)
{
+ (void)dsc_bytes_per_pixel;
+ (void)dsc_slice_width;
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
REG_UPDATE(DP_DSC_CNTL, DP_DSC_MODE, dsc_mode == OPTC_DSC_DISABLED ? 0 : 1);
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c
index fd5d1dbf9dc6..de24dcd27e6c 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn35/dcn35_dio_stream_encoder.c
@@ -369,6 +369,7 @@ static void enc35_stream_encoder_map_to_link(
uint32_t stream_enc_inst,
uint32_t link_enc_inst)
{
+ (void)stream_enc_inst;
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
ASSERT(stream_enc_inst < 5 && link_enc_inst < 5);
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
index 99aab70ef3e1..2d33ed0c062d 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn401/dcn401_dio_stream_encoder.c
@@ -57,6 +57,8 @@ static void enc401_dp_set_odm_combine(
struct stream_encoder *enc,
bool odm_combine)
{
+ (void)enc;
+ (void)odm_combine;
}
/* setup stream encoder in dvi mode */
@@ -710,6 +712,7 @@ void enc401_stream_encoder_map_to_link(
uint32_t stream_enc_inst,
uint32_t link_enc_inst)
{
+ (void)stream_enc_inst;
struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
REG_UPDATE(STREAM_MAPPER_CONTROL,
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c
new file mode 100644
index 000000000000..35dfe3bb0c55
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "reg_helper.h"
+
+#include "core_types.h"
+#include "link_encoder.h"
+#include "dcn35/dcn35_dio_link_encoder.h"
+#include "dcn42_dio_link_encoder.h"
+
+#ifndef MIN
+#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
+#endif
+
+#define CTX \
+ enc10->base.ctx
+#define DC_LOGGER \
+ enc10->base.ctx->logger
+
+#define REG(reg)\
+ (enc10->link_regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+ enc10->link_shift->field_name, enc10->link_mask->field_name
+
+#define HPD_REG(reg)\
+ (enc10->hpd_regs->reg)
+
+#define HPD_REG_GET(reg_name, field, val) \
+ generic_reg_get(CTX, HPD_REG(reg_name), \
+ FN(reg_name, field), val)
+
+#define HPD_REG_SET_N(reg_name, n, initial_val, ...) \
+ generic_reg_set_ex(CTX, \
+ HPD_REG(reg_name), \
+ initial_val, \
+ n, __VA_ARGS__)
+
+#define HPD_REG_SET_2(reg, init_value, f1, v1, f2, v2) \
+ HPD_REG_SET_N(reg, 2, init_value, \
+ FN(reg, f1), v1,\
+ FN(reg, f2), v2)
+
+bool dcn42_get_hpd_state(struct link_encoder *enc)
+{
+ struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+ uint32_t state;
+
+ HPD_REG_GET(DC_HPD_INT_STATUS, DC_HPD_SENSE, &state);
+
+ return state;
+}
+
+bool dcn42_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms)
+{
+ struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+
+ HPD_REG_SET_2(DC_HPD_TOGGLE_FILT_CNTL, 0,
+ DC_HPD_CONNECT_INT_DELAY, delay_on_connect_in_ms,
+ DC_HPD_DISCONNECT_INT_DELAY, delay_on_disconnect_in_ms);
+
+ return true;
+}
+
+static const struct link_encoder_funcs dcn42_link_enc_funcs = {
+ .read_state = link_enc2_read_state,
+ .validate_output_with_stream =
+ dcn30_link_encoder_validate_output_with_stream,
+ .hw_init = dcn35_link_encoder_init,
+ .setup = dcn35_link_encoder_setup,
+ .enable_tmds_output = dcn10_link_encoder_enable_tmds_output,
+ .enable_dp_output = dcn35_link_encoder_enable_dp_output,
+ .enable_dp_mst_output = dcn35_link_encoder_enable_dp_mst_output,
+ .disable_output = dcn35_link_encoder_disable_output,
+ .dp_set_lane_settings = dcn10_link_encoder_dp_set_lane_settings,
+ .dp_set_phy_pattern = dcn10_link_encoder_dp_set_phy_pattern,
+ .update_mst_stream_allocation_table =
+ dcn10_link_encoder_update_mst_stream_allocation_table,
+ .psr_program_dp_dphy_fast_training =
+ dcn10_psr_program_dp_dphy_fast_training,
+ .psr_program_secondary_packet = dcn10_psr_program_secondary_packet,
+ .connect_dig_be_to_fe = dcn10_link_encoder_connect_dig_be_to_fe,
+ .enable_hpd = dcn10_link_encoder_enable_hpd,
+ .disable_hpd = dcn10_link_encoder_disable_hpd,
+ .is_dig_enabled = dcn35_is_dig_enabled,
+ .destroy = dcn10_link_encoder_destroy,
+ .fec_set_enable = enc2_fec_set_enable,
+ .fec_set_ready = enc2_fec_set_ready,
+ .fec_is_active = enc2_fec_is_active,
+ .get_dig_frontend = dcn10_get_dig_frontend,
+ .get_dig_mode = dcn401_get_dig_mode,
+ .is_in_alt_mode = dcn32_link_encoder_is_in_alt_mode,
+ .get_max_link_cap = dcn32_link_encoder_get_max_link_cap,
+ .set_dio_phy_mux = dcn31_link_encoder_set_dio_phy_mux,
+ .enable_dpia_output = dcn35_link_encoder_enable_dpia_output,
+ .disable_dpia_output = dcn35_link_encoder_disable_dpia_output,
+ .get_hpd_state = dcn42_get_hpd_state,
+ .program_hpd_filter = dcn42_program_hpd_filter,
+};
+
+void dcn42_link_encoder_construct(
+ struct dcn20_link_encoder *enc20,
+ const struct encoder_init_data *init_data,
+ const struct encoder_feature_support *enc_features,
+ const struct dcn10_link_enc_registers *link_regs,
+ const struct dcn10_link_enc_aux_registers *aux_regs,
+ const struct dcn10_link_enc_hpd_registers *hpd_regs,
+ const struct dcn10_link_enc_shift *link_shift,
+ const struct dcn10_link_enc_mask *link_mask)
+{
+ struct bp_connector_speed_cap_info bp_cap_info = {0};
+ const struct dc_vbios_funcs *bp_funcs = init_data->ctx->dc_bios->funcs;
+ enum bp_result result = BP_RESULT_OK;
+ struct dcn10_link_encoder *enc10 = &enc20->enc10;
+
+ enc10->base.funcs = &dcn42_link_enc_funcs;
+ enc10->base.ctx = init_data->ctx;
+ enc10->base.id = init_data->encoder;
+
+ enc10->base.hpd_source = init_data->hpd_source;
+ enc10->base.connector = init_data->connector;
+
+
+ enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
+
+ enc10->base.features = *enc_features;
+ if (enc10->base.connector.id == CONNECTOR_ID_USBC)
+ enc10->base.features.flags.bits.DP_IS_USB_C = 1;
+
+ enc10->base.transmitter = init_data->transmitter;
+
+ /* set the flag to indicate whether driver poll the I2C data pin
+ * while doing the DP sink detect
+ */
+
+/* if (dal_adapter_service_is_feature_supported(as,
+ FEATURE_DP_SINK_DETECT_POLL_DATA_PIN))
+ enc10->base.features.flags.bits.
+ DP_SINK_DETECT_POLL_DATA_PIN = true;*/
+
+ enc10->base.output_signals =
+ SIGNAL_TYPE_DVI_SINGLE_LINK |
+ SIGNAL_TYPE_DVI_DUAL_LINK |
+ SIGNAL_TYPE_LVDS |
+ SIGNAL_TYPE_DISPLAY_PORT |
+ SIGNAL_TYPE_DISPLAY_PORT_MST |
+ SIGNAL_TYPE_EDP |
+ SIGNAL_TYPE_HDMI_TYPE_A;
+
+ enc10->link_regs = link_regs;
+ enc10->aux_regs = aux_regs;
+ enc10->hpd_regs = hpd_regs;
+ enc10->link_shift = link_shift;
+ enc10->link_mask = link_mask;
+
+ switch (enc10->base.transmitter) {
+ case TRANSMITTER_UNIPHY_A:
+ enc10->base.preferred_engine = ENGINE_ID_DIGA;
+ break;
+ case TRANSMITTER_UNIPHY_B:
+ enc10->base.preferred_engine = ENGINE_ID_DIGB;
+ break;
+ case TRANSMITTER_UNIPHY_C:
+ enc10->base.preferred_engine = ENGINE_ID_DIGC;
+ break;
+ case TRANSMITTER_UNIPHY_D:
+ enc10->base.preferred_engine = ENGINE_ID_DIGD;
+ break;
+ case TRANSMITTER_UNIPHY_E:
+ enc10->base.preferred_engine = ENGINE_ID_DIGE;
+ break;
+ default:
+ ASSERT_CRITICAL(false);
+ enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
+ }
+
+ /* default to one to mirror Windows behavior */
+ enc10->base.features.flags.bits.HDMI_6GB_EN = 1;
+
+ if (bp_funcs->get_connector_speed_cap_info)
+ result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios,
+ enc10->base.connector, &bp_cap_info);
+
+ /* Override features with DCE-specific values */
+ if (result == BP_RESULT_OK) {
+ enc10->base.features.flags.bits.IS_HBR2_CAPABLE =
+ bp_cap_info.DP_HBR2_EN;
+ enc10->base.features.flags.bits.IS_HBR3_CAPABLE =
+ bp_cap_info.DP_HBR3_EN;
+ enc10->base.features.flags.bits.HDMI_6GB_EN = bp_cap_info.HDMI_6GB_EN;
+ enc10->base.features.flags.bits.IS_DP2_CAPABLE = 1;
+ enc10->base.features.flags.bits.IS_UHBR10_CAPABLE = bp_cap_info.DP_UHBR10_EN;
+ enc10->base.features.flags.bits.IS_UHBR13_5_CAPABLE = bp_cap_info.DP_UHBR13_5_EN;
+ enc10->base.features.flags.bits.IS_UHBR20_CAPABLE = bp_cap_info.DP_UHBR20_EN;
+ } else {
+ DC_LOG_WARNING("%s: Failed to get encoder_cap_info from VBIOS with error code %d!\n",
+ __func__,
+ result);
+ }
+ if (enc10->base.ctx->dc->debug.hdmi20_disable) {
+ enc10->base.features.flags.bits.HDMI_6GB_EN = 0;
+ }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.h
new file mode 100644
index 000000000000..4b5a9594f279
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_link_encoder.h
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __DC_LINK_ENCODER__DCN42_H__
+#define __DC_LINK_ENCODER__DCN42_H__
+
+#include "dcn401/dcn401_dio_link_encoder.h"
+
+#define LINK_ENCODER_MASK_SH_LIST_DCN42(mask_sh) \
+ LE_SF(DIG0_DIG_BE_EN_CNTL, DIG_BE_ENABLE, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CNTL, DIG_RB_SWITCH_EN, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CNTL, DIG_HPD_SELECT, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_MODE, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_CLK_EN, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SOFT_RESET, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CLK_CNTL, HDCP_SOFT_RESET, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_CLOCK_ON, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_HDCP_CLOCK_ON, mask_sh),\
+ LE_SF(DIG0_DIG_BE_CLK_CNTL, DIG_BE_SYMCLK_G_TMDS_CLOCK_ON, mask_sh),\
+ LE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\
+ LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_BYPASS, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE0, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE1, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE2, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_ATEST_SEL_LANE3, mask_sh),\
+ LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_EN, mask_sh),\
+ LE_SF(DP0_DP_DPHY_PRBS_CNTL, DPHY_PRBS_SEL, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM1, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM2, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM0, DPHY_SYM3, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM4, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM5, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM1, DPHY_SYM6, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM7, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SYM2, DPHY_SYM8, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_BS_COUNT, mask_sh),\
+ LE_SF(DP0_DP_DPHY_SCRAM_CNTL, DPHY_SCRAMBLER_ADVANCE, mask_sh),\
+ LE_SF(DP0_DP_DPHY_FAST_TRAINING, DPHY_RX_FAST_TRAINING_CAPABLE, mask_sh),\
+ LE_SF(DP0_DP_DPHY_BS_SR_SWAP_CNTL, DPHY_LOAD_BS_COUNT, mask_sh),\
+ LE_SF(DP0_DP_DPHY_TRAINING_PATTERN_SEL, DPHY_TRAINING_PATTERN_SEL, mask_sh),\
+ LE_SF(DP0_DP_DPHY_HBR2_PATTERN_CONTROL, DP_DPHY_HBR2_PATTERN_CONTROL, mask_sh),\
+ LE_SF(DP0_DP_LINK_CNTL, DP_LINK_TRAINING_COMPLETE, mask_sh),\
+ LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_IDLE_BS_INTERVAL, mask_sh),\
+ LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VBID_DISABLE, mask_sh),\
+ LE_SF(DP0_DP_LINK_FRAMING_CNTL, DP_VID_ENHANCED_FRAME_MODE, mask_sh),\
+ LE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\
+ LE_SF(DP0_DP_CONFIG, DP_UDI_LANES, mask_sh),\
+ LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_LINE_NUM, mask_sh),\
+ LE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP0_PRIORITY, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC0, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SRC1, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT0, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT0, DP_MSE_SAT_SLOT_COUNT1, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC2, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SRC3, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT2, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT1, DP_MSE_SAT_SLOT_COUNT3, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_SAT_UPDATE, mask_sh),\
+ LE_SF(DP0_DP_MSE_SAT_UPDATE, DP_MSE_16_MTP_KEEPOUT, mask_sh),\
+ LE_SF(DP_AUX0_AUX_CONTROL, AUX_HPD_SEL, mask_sh),\
+ LE_SF(DP_AUX0_AUX_CONTROL, AUX_LS_READ_EN, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_RECEIVE_WINDOW, mask_sh),\
+ LE_SF(HPD0_DC_HPD_CONTROL, DC_HPD_EN, mask_sh),\
+ LE_SF(HPD0_DC_HPD_INT_STATUS, DC_HPD_SENSE, mask_sh),\
+ LE_SF(HPD0_DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_CONNECT_INT_DELAY, mask_sh),\
+ LE_SF(HPD0_DC_HPD_TOGGLE_FILT_CNTL, DC_HPD_DISCONNECT_INT_DELAY, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_EN, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_READY_SHADOW, mask_sh),\
+ LE_SF(DP0_DP_DPHY_CNTL, DPHY_FEC_ACTIVE_STATUS, mask_sh),\
+ LE_SF(DIG0_TMDS_CTL_BITS, TMDS_CTL0, mask_sh), \
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_START_WINDOW, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_HALF_SYM_DETECT_LEN, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_TRANSITION_FILTER_EN, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_START, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_ALLOW_BELOW_THRESHOLD_STOP, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_PHASE_DETECT_LEN, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \
+ LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\
+ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, DISPCLK_R_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, DISPCLK_G_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, REFCLK_R_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, REFCLK_G_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SOCCLK_G_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLK_FE_R_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLK_FE_G_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLK_R_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLK_G_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, DIO_FGCG_REP_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, DISPCLK_G_HDCP_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLKA_G_HDCP_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLKB_G_HDCP_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLKC_G_HDCP_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLKD_G_HDCP_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLKE_G_HDCP_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLKF_G_HDCP_GATE_DIS, mask_sh),\
+ LE_SF(DIO_CLK_CNTL, SYMCLKG_G_HDCP_GATE_DIS, mask_sh)
+
+void dcn42_link_encoder_construct(
+ struct dcn20_link_encoder *enc20,
+ const struct encoder_init_data *init_data,
+ const struct encoder_feature_support *enc_features,
+ const struct dcn10_link_enc_registers *link_regs,
+ const struct dcn10_link_enc_aux_registers *aux_regs,
+ const struct dcn10_link_enc_hpd_registers *hpd_regs,
+ const struct dcn10_link_enc_shift *link_shift,
+ const struct dcn10_link_enc_mask *link_mask);
+
+bool dcn42_get_hpd_state(struct link_encoder *enc);
+bool dcn42_program_hpd_filter(struct link_encoder *enc, int delay_on_connect_in_ms, int delay_on_disconnect_in_ms);
+
+#endif /* __DC_LINK_ENCODER__DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c
new file mode 100644
index 000000000000..65afbfcaa96b
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.c
@@ -0,0 +1,522 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dc_bios_types.h"
+#include "dcn30/dcn30_dio_stream_encoder.h"
+#include "dcn32/dcn32_dio_stream_encoder.h"
+#include "dcn35/dcn35_dio_stream_encoder.h"
+#include "dcn401/dcn401_dio_stream_encoder.h"
+#include "dcn31/dcn31_apg.h"
+
+#include "dcn42_dio_stream_encoder.h"
+#include "reg_helper.h"
+#include "hw_shared.h"
+#include "link_service.h"
+#include "dpcd_defs.h"
+
+#define DC_LOGGER \
+ enc1->base.ctx->logger
+
+#define REG(reg)\
+ (enc1->regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+ enc1->se_shift->field_name, enc1->se_mask->field_name
+
+#define VBI_LINE_0 0
+#define HDMI_CLOCK_CHANNEL_RATE_MORE_340M 340000
+
+#define CTX \
+ enc1->base.ctx
+
+/* setup stream encoder in hdmi mode */
+static void enc42_stream_encoder_hdmi_set_stream_attribute(
+ struct stream_encoder *enc,
+ struct dc_crtc_timing *crtc_timing,
+ int actual_pix_clk_khz,
+ bool enable_audio)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ if (!enc->ctx->dc->debug.avoid_vbios_exec_table) {
+ struct bp_encoder_control cntl = {0};
+
+ cntl.action = ENCODER_CONTROL_SETUP;
+ cntl.engine_id = enc1->base.id;
+ cntl.signal = SIGNAL_TYPE_HDMI_TYPE_A;
+ cntl.enable_dp_audio = enable_audio;
+ cntl.pixel_clock = actual_pix_clk_khz;
+ cntl.lanes_number = LANE_COUNT_FOUR;
+
+ if (enc1->base.bp->funcs->encoder_control(
+ enc1->base.bp, &cntl) != BP_RESULT_OK)
+ return;
+
+ } else {
+
+ //Set pattern for clock channel, default vlue 0x63 does not work
+ REG_UPDATE(DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, 0x1F);
+
+ //DIG_BE_TMDS_HDMI_MODE : TMDS-HDMI mode is already set in link_encoder_setup
+
+ //DIG_SOURCE_SELECT is already set in dig_connect_to_otg
+
+ /* DIG_START is removed from the register spec */
+ }
+
+ /* Configure pixel encoding */
+ enc401_stream_encoder_set_stream_attribute_helper(enc1, crtc_timing);
+
+ /* setup HDMI engine */
+ REG_UPDATE_4(HDMI_CONTROL,
+ HDMI_DEEP_COLOR_ENABLE, 0,
+ HDMI_DATA_SCRAMBLE_EN, 0,
+ HDMI_NO_EXTRA_NULL_PACKET_FILLED, 1,
+ HDMI_CLOCK_CHANNEL_RATE, 0);
+
+ /* Configure color depth */
+ switch (crtc_timing->display_color_depth) {
+ case COLOR_DEPTH_888:
+ REG_UPDATE(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, 0);
+ break;
+ case COLOR_DEPTH_101010:
+ if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DEEP_COLOR_DEPTH, 1,
+ HDMI_DEEP_COLOR_ENABLE, 0);
+ } else {
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DEEP_COLOR_DEPTH, 1,
+ HDMI_DEEP_COLOR_ENABLE, 1);
+ }
+ break;
+ case COLOR_DEPTH_121212:
+ if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) {
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DEEP_COLOR_DEPTH, 2,
+ HDMI_DEEP_COLOR_ENABLE, 0);
+ } else {
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DEEP_COLOR_DEPTH, 2,
+ HDMI_DEEP_COLOR_ENABLE, 1);
+ }
+ break;
+ case COLOR_DEPTH_161616:
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DEEP_COLOR_DEPTH, 3,
+ HDMI_DEEP_COLOR_ENABLE, 1);
+ break;
+ default:
+ break;
+ }
+
+ if (actual_pix_clk_khz >= HDMI_CLOCK_CHANNEL_RATE_MORE_340M) {
+ /* enable HDMI data scrambler
+ * HDMI_CLOCK_CHANNEL_RATE_MORE_340M
+ * Clock channel frequency is 1/4 of character rate.
+ */
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DATA_SCRAMBLE_EN, 1,
+ HDMI_CLOCK_CHANNEL_RATE, 1);
+ } else if (crtc_timing->flags.LTE_340MCSC_SCRAMBLE) {
+
+ /* TODO: New feature for DCE11, still need to implement */
+
+ /* enable HDMI data scrambler
+ * HDMI_CLOCK_CHANNEL_FREQ_EQUAL_TO_CHAR_RATE
+ * Clock channel frequency is the same
+ * as character rate
+ */
+ REG_UPDATE_2(HDMI_CONTROL,
+ HDMI_DATA_SCRAMBLE_EN, 1,
+ HDMI_CLOCK_CHANNEL_RATE, 0);
+ }
+
+ /* Enable transmission of General Control packet on every frame */
+ REG_UPDATE_3(HDMI_VBI_PACKET_CONTROL,
+ HDMI_GC_CONT, 1,
+ HDMI_GC_SEND, 1,
+ HDMI_NULL_SEND, 1);
+
+ /* Disable Audio Content Protection packet transmission */
+ REG_UPDATE(HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, 0);
+ /* following belongs to audio */
+ /* Enable Audio InfoFrame packet transmission. */
+ REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, 1);
+
+ /* Select line number on which to send Audio InfoFrame packets */
+ REG_UPDATE(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_LINE,
+ VBI_LINE_0 + 2);
+
+ /* set HDMI GC AVMUTE */
+ REG_UPDATE(HDMI_GC, HDMI_GC_AVMUTE, 0);
+}
+
+static void enc42_stream_encoder_stop_dp_info_packets(
+ struct stream_encoder *enc)
+{
+ /* stop generic packets on DP */
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+ uint32_t value = 0;
+
+ REG_SET_9(DP_SEC_CNTL, 0,
+ DP_SEC_GSP0_ENABLE, 0,
+ DP_SEC_GSP1_ENABLE, 0,
+ DP_SEC_GSP2_ENABLE, 0,
+ DP_SEC_GSP3_ENABLE, 0,
+ DP_SEC_GSP4_ENABLE, 0,
+ DP_SEC_GSP5_ENABLE, 0,
+ DP_SEC_GSP6_ENABLE, 0,
+ DP_SEC_GSP7_ENABLE, 0,
+ DP_SEC_STREAM_ENABLE, 0);
+
+ /* this register shared with audio info frame.
+ * therefore we need to keep master enabled
+ * if at least one of the fields is not 0
+ */
+ value = REG_READ(DP_SEC_CNTL);
+ if (value)
+ REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1);
+}
+
+static void enc42_stream_encoder_update_hdmi_info_packets(
+ struct stream_encoder *enc,
+ const struct encoder_info_frame *info_frame)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ REG_UPDATE(HDMI_DB_CONTROL, HDMI_DB_DISABLE, 1);
+ REG_UPDATE(DIG_FE_AUDIO_CNTL, APG_CLOCK_ENABLE, 1);
+
+ /*Always add mandatory packets first followed by optional ones*/
+ enc3_update_hdmi_info_packet(enc1, 0, &info_frame->avi);
+ enc3_update_hdmi_info_packet(enc1, 5, &info_frame->hfvsif);
+ enc3_update_hdmi_info_packet(enc1, 2, &info_frame->gamut);
+ enc3_update_hdmi_info_packet(enc1, 1, &info_frame->vendor);
+ enc3_update_hdmi_info_packet(enc1, 3, &info_frame->spd);
+ enc3_update_hdmi_info_packet(enc1, 4, &info_frame->hdrsmd);
+ enc3_update_hdmi_info_packet(enc1, 6, &info_frame->vtem);
+}
+
+static void enc42_dp_set_dsc_pps_info_packet(struct stream_encoder *enc,
+ bool enable,
+ uint8_t *dsc_packed_pps,
+ bool immediate_update)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ if (enable) {
+ struct dc_info_packet pps_sdp;
+ int i;
+
+ /* Configure for PPS packet size (128 bytes) */
+ REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 1);
+
+ /* Load PPS into infoframe (SDP) registers */
+ pps_sdp.valid = true;
+ pps_sdp.hb0 = 0;
+ pps_sdp.hb1 = DC_DP_INFOFRAME_TYPE_PPS;
+ pps_sdp.hb2 = 127;
+ pps_sdp.hb3 = 0;
+
+ for (i = 0; i < 4; i++) {
+ memcpy(pps_sdp.sb, &dsc_packed_pps[i * 32], 32);
+ enc1->base.vpg->funcs->update_generic_info_packet(
+ enc1->base.vpg,
+ 11 + i,
+ &pps_sdp,
+ immediate_update);
+ }
+
+ /* SW should make sure VBID[6] update line number is bigger
+ * than PPS transmit line number
+ */
+ REG_UPDATE(DP_GSP11_CNTL,
+ DP_SEC_GSP11_LINE_NUM, 2);
+ REG_UPDATE_2(DP_MSA_VBID_MISC,
+ DP_VBID6_LINE_REFERENCE, 0,
+ DP_VBID6_LINE_NUM, 3);
+
+ /* Send PPS data at the line number specified above.
+ * DP spec requires PPS to be sent only when it changes, however since
+ * decoder has to be able to handle its change on every frame, we're
+ * sending it always (i.e. on every frame) to reduce the chance it'd be
+ * missed by decoder. If it turns out required to send PPS only when it
+ * changes, we can use DP_SEC_GSP11_SEND register.
+ */
+ REG_UPDATE(DP_GSP11_CNTL,
+ DP_SEC_GSP11_ENABLE, 1);
+ REG_UPDATE(DP_SEC_CNTL,
+ DP_SEC_STREAM_ENABLE, 1);
+ } else {
+ /* Disable Generic Stream Packet 11 (GSP) transmission */
+ REG_UPDATE(DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, 0);
+ REG_UPDATE(DP_SEC_CNTL2, DP_SEC_GSP11_PPS, 0);
+ }
+}
+
+static void enc42_se_dp_audio_setup(
+ struct stream_encoder *enc,
+ unsigned int az_inst,
+ struct audio_info *info)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+ enc42_se_enable_audio_clock(enc, true);
+
+ REG_UPDATE(DIG_FE_AUDIO_CNTL,
+ DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst);
+
+ enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info);
+}
+
+#define DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT 0x8000
+#define DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC 1
+
+static void enc42_se_setup_dp_audio(
+ struct stream_encoder *enc)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ /* --- DP Audio packet configurations --- */
+
+ /* ATP Configuration */
+ REG_SET(DP_SEC_AUD_N, 0,
+ DP_SEC_AUD_N, DP_SEC_AUD_N__DP_SEC_AUD_N__DEFAULT);
+
+ /* Async/auto-calc timestamp mode */
+ REG_SET(DP_SEC_TIMESTAMP, 0, DP_SEC_TIMESTAMP_MODE,
+ DP_SEC_TIMESTAMP__DP_SEC_TIMESTAMP_MODE__AUTO_CALC);
+}
+
+static void enc42_se_dp_audio_enable(
+ struct stream_encoder *enc)
+{
+ ASSERT (enc->apg);
+ enc42_se_enable_audio_clock(enc, true);
+ /*APG_CONTROL2 for DP*/
+ enc42_se_setup_dp_audio(enc);
+ /*DP_SEC_CNTL programming*/
+ enc1_se_enable_dp_audio(enc);
+ /*APG_en*/
+ enc->apg->funcs->enable_apg(enc->apg);
+
+}
+
+static void enc42_se_disable_dp_audio(
+ struct stream_encoder *enc)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+ uint32_t value = 0;
+
+ /* Disable Audio packets */
+ REG_UPDATE_5(DP_SEC_CNTL,
+ DP_SEC_ASP_ENABLE, 0,
+ DP_SEC_ATP_ENABLE, 0,
+ DP_SEC_AIP_ENABLE, 0,
+ DP_SEC_ACM_ENABLE, 0,
+ DP_SEC_STREAM_ENABLE, 0);
+
+ /* This register shared with encoder info frame. Therefore we need to
+ * keep master enabled if at least on of the fields is not 0
+ */
+ value = REG_READ(DP_SEC_CNTL);
+ if (value != 0)
+ REG_UPDATE(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, 1);
+}
+
+static void enc42_se_dp_audio_disable(
+ struct stream_encoder *enc)
+{
+
+ enc->apg->funcs->disable_apg(enc->apg);
+ enc42_se_disable_dp_audio(enc);
+ enc42_se_enable_audio_clock(enc, false);
+}
+
+static void enc42_se_setup_hdmi_audio(
+ struct stream_encoder *enc,
+ const struct audio_crtc_info *crtc_info)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ struct audio_clock_info audio_clock_info = {0};
+
+ /* HDMI_AUDIO_PACKET_CONTROL */
+ REG_UPDATE(HDMI_AUDIO_PACKET_CONTROL,
+ HDMI_AUDIO_DELAY_EN, 1);
+
+ /* HDMI_ACR_PACKET_CONTROL */
+ REG_UPDATE_2(HDMI_ACR_PACKET_CONTROL,
+ HDMI_ACR_AUTO_SEND, 1,
+ HDMI_ACR_SOURCE, 0);
+
+ /* Program audio clock sample/regeneration parameters */
+ get_audio_clock_info(crtc_info->color_depth,
+ crtc_info->requested_pixel_clock_100Hz,
+ crtc_info->calculated_pixel_clock_100Hz,
+ &audio_clock_info);
+ DC_LOG_HW_AUDIO("\n%s:Input::requested_pixel_clock_100Hz = %d" \
+ "calculated_pixel_clock_100Hz = %d\n", __func__,\
+ crtc_info->requested_pixel_clock_100Hz, \
+ crtc_info->calculated_pixel_clock_100Hz);
+
+ /* HDMI_ACR_32_0__HDMI_ACR_CTS_32_MASK */
+ REG_UPDATE(HDMI_ACR_32_0, HDMI_ACR_CTS_32, audio_clock_info.cts_32khz);
+
+ /* HDMI_ACR_32_1__HDMI_ACR_N_32_MASK */
+ REG_UPDATE(HDMI_ACR_32_1, HDMI_ACR_N_32, audio_clock_info.n_32khz);
+
+ /* HDMI_ACR_44_0__HDMI_ACR_CTS_44_MASK */
+ REG_UPDATE(HDMI_ACR_44_0, HDMI_ACR_CTS_44, audio_clock_info.cts_44khz);
+
+ /* HDMI_ACR_44_1__HDMI_ACR_N_44_MASK */
+ REG_UPDATE(HDMI_ACR_44_1, HDMI_ACR_N_44, audio_clock_info.n_44khz);
+
+ /* HDMI_ACR_48_0__HDMI_ACR_CTS_48_MASK */
+ REG_UPDATE(HDMI_ACR_48_0, HDMI_ACR_CTS_48, audio_clock_info.cts_48khz);
+
+ /* HDMI_ACR_48_1__HDMI_ACR_N_48_MASK */
+ REG_UPDATE(HDMI_ACR_48_1, HDMI_ACR_N_48, audio_clock_info.n_48khz);
+
+ /* Video driver cannot know in advance which sample rate will
+ * be used by HD Audio driver
+ * HDMI_ACR_PACKET_CONTROL__HDMI_ACR_N_MULTIPLE field is
+ * programmed below in interruppt callback
+ */
+}
+
+static void enc42_se_hdmi_audio_disable(
+ struct stream_encoder *enc)
+{
+ ASSERT (enc->apg);
+ enc->apg->funcs->disable_apg(enc->apg);
+ enc42_se_enable_audio_clock(enc, false);
+}
+
+void enc42_se_enable_audio_clock(
+ struct stream_encoder *enc,
+ bool enable)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ REG_UPDATE(DIG_FE_AUDIO_CNTL, APG_CLOCK_ENABLE, !!enable);
+}
+
+
+static void enc42_se_hdmi_audio_setup(
+ struct stream_encoder *enc,
+ unsigned int az_inst,
+ struct audio_info *info,
+ struct audio_crtc_info *audio_crtc_info)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ ASSERT (enc->apg);
+ enc42_se_enable_audio_clock(enc, true);
+ /*ACR setup*/
+ enc42_se_setup_hdmi_audio(enc, audio_crtc_info);
+
+ REG_UPDATE(DIG_FE_AUDIO_CNTL,
+ DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst);
+
+ /*APG_DBG_GEN_CONTROL*/
+ enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info);
+ /*APG enable*/
+ enc->apg->funcs->enable_apg(enc->apg);
+}
+
+static void enc42_audio_mute_control(
+ struct stream_encoder *enc,
+ bool mute)
+{
+ if (mute)
+ enc->apg->funcs->disable_apg(enc->apg);
+ else
+ enc->apg->funcs->enable_apg(enc->apg);
+}
+void enc42_reset_hdmi_stream_attribute(
+ struct stream_encoder *enc)
+{
+ struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc);
+
+ REG_UPDATE_3(HDMI_CONTROL,
+ HDMI_DEEP_COLOR_ENABLE, 0,
+ HDMI_DATA_SCRAMBLE_EN, 0,
+ HDMI_CLOCK_CHANNEL_RATE, 0);
+}
+
+static const struct stream_encoder_funcs dcn42_str_enc_funcs = {
+ .dp_set_stream_attribute =
+ enc401_stream_encoder_dp_set_stream_attribute,
+ .hdmi_set_stream_attribute =
+ enc42_stream_encoder_hdmi_set_stream_attribute,
+ .dvi_set_stream_attribute =
+ enc401_stream_encoder_dvi_set_stream_attribute,
+ .set_throttled_vcp_size =
+ enc1_stream_encoder_set_throttled_vcp_size,
+ .update_hdmi_info_packets =
+ enc42_stream_encoder_update_hdmi_info_packets,
+ .stop_hdmi_info_packets =
+ enc3_stream_encoder_stop_hdmi_info_packets,
+ .update_dp_info_packets_sdp_line_num =
+ enc3_stream_encoder_update_dp_info_packets_sdp_line_num,
+ .update_dp_info_packets =
+ enc3_stream_encoder_update_dp_info_packets,
+ .stop_dp_info_packets =
+ enc42_stream_encoder_stop_dp_info_packets,
+ .dp_blank =
+ enc1_stream_encoder_dp_blank,
+ .dp_unblank =
+ enc401_stream_encoder_dp_unblank,
+ .audio_mute_control = enc42_audio_mute_control,
+
+ .dp_audio_setup = enc42_se_dp_audio_setup,
+ .dp_audio_enable = enc42_se_dp_audio_enable,
+ .dp_audio_disable = enc42_se_dp_audio_disable,
+
+ .hdmi_audio_setup = enc42_se_hdmi_audio_setup,
+ .hdmi_audio_disable = enc42_se_hdmi_audio_disable,
+ .setup_stereo_sync = enc1_setup_stereo_sync,
+ .set_avmute = enc1_stream_encoder_set_avmute,
+ .dig_connect_to_otg = enc1_dig_connect_to_otg,
+ .dig_source_otg = enc1_dig_source_otg,
+
+ .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format,
+
+ .enc_read_state = enc401_read_state,
+ .dp_set_dsc_config = NULL,
+ .dp_set_dsc_pps_info_packet = enc42_dp_set_dsc_pps_info_packet,
+ .set_dynamic_metadata = enc401_set_dynamic_metadata,
+ .hdmi_reset_stream_attribute = enc42_reset_hdmi_stream_attribute,
+ .enable_stream = enc401_stream_encoder_enable,
+
+ .set_input_mode = enc401_set_dig_input_mode,
+ .enable_fifo = enc35_enable_fifo,
+ .disable_fifo = enc35_disable_fifo,
+ .map_stream_to_link = enc401_stream_encoder_map_to_link,
+};
+
+void dcn42_dio_stream_encoder_construct(
+ struct dcn10_stream_encoder *enc1,
+ struct dc_context *ctx,
+ struct dc_bios *bp,
+ enum engine_id eng_id,
+ struct vpg *vpg,
+ struct apg *apg,
+ const struct dcn10_stream_enc_registers *regs,
+ const struct dcn10_stream_encoder_shift *se_shift,
+ const struct dcn10_stream_encoder_mask *se_mask)
+{
+ enc1->base.funcs = &dcn42_str_enc_funcs;
+ enc1->base.ctx = ctx;
+ enc1->base.id = eng_id;
+ enc1->base.bp = bp;
+ enc1->base.vpg = vpg;
+ enc1->base.apg = apg;
+ enc1->regs = regs;
+ enc1->se_shift = se_shift;
+ enc1->se_mask = se_mask;
+ enc1->base.stream_enc_inst = vpg->inst;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.h
new file mode 100644
index 000000000000..7a98fee46081
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dio/dcn42/dcn42_dio_stream_encoder.h
@@ -0,0 +1,206 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 - Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_DIO_STREAM_ENCODER_DCN42_H__
+#define __DC_DIO_STREAM_ENCODER_DCN42_H__
+
+#include "dcn30/dcn30_vpg.h"
+#include "stream_encoder.h"
+#include "dcn20/dcn20_stream_encoder.h"
+
+#define SE_COMMON_MASK_SH_LIST_DCN42(mask_sh)\
+ SE_SF(DP0_DP_PIXEL_FORMAT, PIXEL_ENCODING_TYPE, mask_sh),\
+ SE_SF(DP0_DP_PIXEL_FORMAT, UNCOMPRESSED_PIXEL_FORMAT, mask_sh),\
+ SE_SF(DP0_DP_PIXEL_FORMAT, UNCOMPRESSED_COMPONENT_DEPTH, mask_sh),\
+ SE_SF(DP0_DP_PIXEL_FORMAT, COMPRESSED_PIXEL_FORMAT, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, HDMI_NO_EXTRA_NULL_PACKET_FILLED, mask_sh),\
+ SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_VBI_PACKET_CONTROL, HDMI_ACP_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\
+ SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\
+ SE_SF(DP0_DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\
+ SE_SF(DP0_DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL1, DP_SEC_GSP5_LINE_REFERENCE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_PENDING, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL4, DP_SEC_GSP4_LINE_NUM, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL5, DP_SEC_GSP5_LINE_NUM, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP4_SEND_ANY_LINE, mask_sh),\
+ SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\
+ SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\
+ SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\
+ SE_SF(DP0_DP_STEER_FIFO, DP_STEER_FIFO_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\
+ SE_SF(DP0_DP_VID_N, DP_VID_N, mask_sh),\
+ SE_SF(DP0_DP_VID_M, DP_VID_M, mask_sh),\
+ SE_SF(DIG0_HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\
+ SE_SF(DIG0_HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\
+ SE_SF(DP0_DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\
+ SE_SF(DP0_DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\
+ SE_SF(DIG1_HDMI_CONTROL, TMDS_PIXEL_ENCODING, mask_sh),\
+ SE_SF(DIG1_HDMI_CONTROL, TMDS_COLOR_FORMAT, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_SELECT, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP4_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP5_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP6_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL, DP_SEC_GSP7_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP7_SEND, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL6, DP_SEC_GSP7_LINE_NUM, mask_sh),\
+ SE_SF(DP0_DP_SEC_CNTL2, DP_SEC_GSP11_PPS, mask_sh),\
+ SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, mask_sh),\
+ SE_SF(DP0_DP_DB_CNTL, DP_DB_DISABLE, mask_sh),\
+ SE_SF(DP0_DP_MSA_COLORIMETRY, DP_MSA_MISC0, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_HTOTAL, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM1, DP_MSA_VTOTAL, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_HSTART, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM2, DP_MSA_VSTART, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCWIDTH, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_HSYNCPOLARITY, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCWIDTH, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM3, DP_MSA_VSYNCPOLARITY, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_HWIDTH, mask_sh),\
+ SE_SF(DP0_DP_MSA_TIMING_PARAM4, DP_MSA_VHEIGHT, mask_sh),\
+ SE_SF(DIG0_HDMI_DB_CONTROL, HDMI_DB_DISABLE, mask_sh),\
+ SE_SF(DP0_DP_VID_TIMING, DP_VID_N_INTERVAL, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CNTL, DIG_SOURCE_SELECT, mask_sh), \
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC2_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC3_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC4_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC5_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC6_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC7_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC8_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC9_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC10_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC11_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC12_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC13_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_CONT, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL6, HDMI_GENERIC14_SEND, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC0_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL1, HDMI_GENERIC1_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC2_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL2, HDMI_GENERIC3_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC4_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL3, HDMI_GENERIC5_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC6_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL4, HDMI_GENERIC7_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC8_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL7, HDMI_GENERIC9_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC10_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL8, HDMI_GENERIC11_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC12_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL9, HDMI_GENERIC13_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_GENERIC_PACKET_CONTROL10, HDMI_GENERIC14_LINE, mask_sh),\
+ SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_REFERENCE, mask_sh),\
+ SE_SF(DP0_DP_MSA_VBID_MISC, DP_VBID6_LINE_NUM, mask_sh),\
+ SE_SF(DME0_DME_CONTROL, METADATA_ENGINE_EN, mask_sh),\
+ SE_SF(DME0_DME_CONTROL, METADATA_HUBP_REQUESTOR_ID, mask_sh),\
+ SE_SF(DME0_DME_CONTROL, METADATA_STREAM_TYPE, mask_sh),\
+ SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_ENABLE, mask_sh),\
+ SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE_REFERENCE, mask_sh),\
+ SE_SF(DP0_DP_SEC_METADATA_TRANSMISSION, DP_SEC_METADATA_PACKET_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_ENABLE, mask_sh),\
+ SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE_REFERENCE, mask_sh),\
+ SE_SF(DIG0_HDMI_METADATA_PACKET_CONTROL, HDMI_METADATA_PACKET_LINE, mask_sh),\
+ SE_SF(DIG0_HDMI_CONTROL, DOLBY_VISION_EN, mask_sh),\
+ SE_SF(DIG0_DIG_FE_EN_CNTL, DIG_FE_ENABLE, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_MODE, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CLK_CNTL, DIG_FE_SOFT_RESET, mask_sh),\
+ SE_SF(DIG0_DIG_FE_CNTL, DIG_STEREOSYNC_GATE_EN, mask_sh),\
+ SE_SF(DP0_DP_SEC_FRAMING4, DP_SST_SDP_SPLITTING, mask_sh),\
+ SE_SF(DIG0_DIG_CLOCK_PATTERN, DIG_CLOCK_PATTERN, mask_sh),\
+ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE, mask_sh),\
+ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, mask_sh),\
+ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, mask_sh),\
+ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET, mask_sh),\
+ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, mask_sh),\
+ SE_SF(DIG0_STREAM_MAPPER_CONTROL, DIG_STREAM_LINK_TARGET, mask_sh),\
+ SE_SF(DIG0_DIG_FE_AUDIO_CNTL, DIG_FE_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, mask_sh),\
+ SE_SF(DIG0_DIG_FE_AUDIO_CNTL, APG_CLOCK_ENABLE, mask_sh)
+
+void dcn42_dio_stream_encoder_construct(
+ struct dcn10_stream_encoder *enc1,
+ struct dc_context *ctx,
+ struct dc_bios *bp,
+ enum engine_id eng_id,
+ struct vpg *vpg,
+ struct apg *apg,
+ const struct dcn10_stream_enc_registers *regs,
+ const struct dcn10_stream_encoder_shift *se_shift,
+ const struct dcn10_stream_encoder_mask *se_mask);
+
+void enc42_se_enable_audio_clock(
+ struct stream_encoder *enc,
+ bool enable);
+
+void enc42_reset_hdmi_stream_attribute(
+ struct stream_encoder *enc);
+#endif /* __DC_DIO_STREAM_ENCODER_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c
index 2655bc194a35..5b2bba0eff0e 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_link_encoder.c
@@ -30,52 +30,92 @@
static bool virtual_link_encoder_validate_output_with_stream(
struct link_encoder *enc,
- const struct dc_stream_state *stream) { return true; }
+ const struct dc_stream_state *stream) {
+ (void)enc;
+ (void)stream;
+ return true;
+ }
-static void virtual_link_encoder_hw_init(struct link_encoder *enc) {}
+static void virtual_link_encoder_hw_init(struct link_encoder *enc)
+{
+ (void)enc;
+}
static void virtual_link_encoder_setup(
- struct link_encoder *enc,
- enum signal_type signal) {}
+ struct link_encoder *enc, enum signal_type signal) {
+ (void)enc;
+ (void)signal;
+ }
static void virtual_link_encoder_enable_tmds_output(
struct link_encoder *enc,
enum clock_source_id clock_source,
enum dc_color_depth color_depth,
enum signal_type signal,
- uint32_t pixel_clock) {}
+ uint32_t pixel_clock) {
+ (void)enc;
+ (void)clock_source;
+ (void)color_depth;
+ (void)signal;
+ (void)pixel_clock;
+ }
static void virtual_link_encoder_enable_dp_output(
struct link_encoder *enc,
const struct dc_link_settings *link_settings,
- enum clock_source_id clock_source) {}
+ enum clock_source_id clock_source) {
+ (void)enc;
+ (void)link_settings;
+ (void)clock_source;
+ }
static void virtual_link_encoder_enable_dp_mst_output(
struct link_encoder *enc,
const struct dc_link_settings *link_settings,
- enum clock_source_id clock_source) {}
+ enum clock_source_id clock_source) {
+ (void)enc;
+ (void)link_settings;
+ (void)clock_source;
+ }
static void virtual_link_encoder_disable_output(
struct link_encoder *link_enc,
- enum signal_type signal) {}
+ enum signal_type signal) {
+ (void)link_enc;
+ (void)signal;
+ }
static void virtual_link_encoder_dp_set_lane_settings(
struct link_encoder *enc,
const struct dc_link_settings *link_settings,
- const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) {}
+ const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]) {
+ (void)enc;
+ (void)link_settings;
+ (void)lane_settings;
+ }
static void virtual_link_encoder_dp_set_phy_pattern(
struct link_encoder *enc,
- const struct encoder_set_dp_phy_pattern_param *param) {}
+ const struct encoder_set_dp_phy_pattern_param *param) {
+ (void)enc;
+ (void)param;
+ }
static void virtual_link_encoder_update_mst_stream_allocation_table(
struct link_encoder *enc,
- const struct link_mst_stream_allocation_table *table) {}
+ const struct link_mst_stream_allocation_table *table) {
+ (void)enc;
+ (void)table;
+ }
static void virtual_link_encoder_connect_dig_be_to_fe(
struct link_encoder *enc,
enum engine_id engine,
- bool connect) {}
+ bool connect) {
+ (void)enc;
+ (void)engine;
+ (void)connect;
+ }
static void virtual_link_encoder_destroy(struct link_encoder **enc)
{
@@ -86,6 +126,7 @@ static void virtual_link_encoder_destroy(struct link_encoder **enc)
static void virtual_link_encoder_get_max_link_cap(struct link_encoder *enc,
struct dc_link_settings *link_settings)
{
+ (void)enc;
/* Set Default link settings */
struct dc_link_settings max_link_cap = {LANE_COUNT_FOUR, LINK_RATE_HIGH,
LINK_SPREAD_05_DOWNSPREAD_30KHZ, false, 0};
diff --git a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c
index a9c8857476ac..27448f2b2467 100644
--- a/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dio/virtual/virtual_stream_encoder.c
@@ -31,80 +31,127 @@ static void virtual_stream_encoder_dp_set_stream_attribute(
struct dc_crtc_timing *crtc_timing,
enum dc_color_space output_color_space,
bool use_vsc_sdp_for_colorimetry,
- uint32_t enable_sdp_splitting) {}
+ uint32_t enable_sdp_splitting) {
+ (void)enc;
+ (void)crtc_timing;
+ (void)output_color_space;
+ (void)use_vsc_sdp_for_colorimetry;
+ (void)enable_sdp_splitting;
+ }
static void virtual_stream_encoder_hdmi_set_stream_attribute(
struct stream_encoder *enc,
struct dc_crtc_timing *crtc_timing,
int actual_pix_clk_khz,
- bool enable_audio) {}
+ bool enable_audio) {
+ (void)enc;
+ (void)crtc_timing;
+ (void)actual_pix_clk_khz;
+ (void)enable_audio;
+ }
static void virtual_stream_encoder_dvi_set_stream_attribute(
struct stream_encoder *enc,
struct dc_crtc_timing *crtc_timing,
- bool is_dual_link) {}
+ bool is_dual_link) {
+ (void)enc;
+ (void)crtc_timing;
+ (void)is_dual_link;
+ }
static void virtual_stream_encoder_set_throttled_vcp_size(
struct stream_encoder *enc,
- struct fixed31_32 avg_time_slots_per_mtp)
-{}
+ struct fixed31_32 avg_time_slots_per_mtp) {
+ (void)enc;
+ (void)avg_time_slots_per_mtp;
+ }
static void virtual_stream_encoder_update_hdmi_info_packets(
struct stream_encoder *enc,
- const struct encoder_info_frame *info_frame) {}
+ const struct encoder_info_frame *info_frame) {
+ (void)enc;
+ (void)info_frame;
+ }
static void virtual_stream_encoder_stop_hdmi_info_packets(
- struct stream_encoder *enc) {}
+ struct stream_encoder *enc) {
+ (void)enc;
+ }
static void virtual_stream_encoder_set_avmute(
- struct stream_encoder *enc,
- bool enable) {}
+ struct stream_encoder *enc, bool enable) {
+ (void)enc;
+ (void)enable;
+ }
static void virtual_stream_encoder_update_dp_info_packets(
struct stream_encoder *enc,
- const struct encoder_info_frame *info_frame) {}
+ const struct encoder_info_frame *info_frame) {
+ (void)enc;
+ (void)info_frame;
+ }
static void virtual_stream_encoder_stop_dp_info_packets(
- struct stream_encoder *enc) {}
+ struct stream_encoder *enc) {
+ (void)enc;
+ }
static void virtual_stream_encoder_dp_blank(
struct dc_link *link,
- struct stream_encoder *enc) {}
+ struct stream_encoder *enc) {
+ (void)link;
+ (void)enc;
+ }
static void virtual_stream_encoder_dp_unblank(
struct dc_link *link,
struct stream_encoder *enc,
- const struct encoder_unblank_param *param) {}
+ const struct encoder_unblank_param *param) {
+ (void)enc;
+ (void)link;
+ (void)param;
+ }
static void virtual_audio_mute_control(
- struct stream_encoder *enc,
- bool mute) {}
+ struct stream_encoder *enc, bool mute) {
+ (void)enc;
+ (void)mute;
+ }
static void virtual_stream_encoder_reset_hdmi_stream_attribute(
- struct stream_encoder *enc)
-{}
+ struct stream_encoder *enc)
+{
+ (void)enc;
+}
static void virtual_enc_dp_set_odm_combine(
- struct stream_encoder *enc,
- bool odm_combine)
-{}
+ struct stream_encoder *enc, bool odm_combine) {
+ (void)enc;
+ (void)odm_combine;
+ }
static void virtual_dig_connect_to_otg(
- struct stream_encoder *enc,
- int tg_inst)
-{}
+ struct stream_encoder *enc, int tg_inst) {
+ (void)enc;
+ (void)tg_inst;
+ }
static void virtual_setup_stereo_sync(
- struct stream_encoder *enc,
- int tg_inst,
- bool enable)
-{}
+ struct stream_encoder *enc,
+ int tg_inst, bool enable) {
+ (void)enc;
+ (void)tg_inst;
+ (void)enable;
+ }
static void virtual_stream_encoder_set_dsc_pps_info_packet(
- struct stream_encoder *enc,
- bool enable,
- uint8_t *dsc_packed_pps,
- bool immediate_update)
-{}
+ struct stream_encoder *enc, bool enable, uint8_t *dsc_packed_pps,
+ bool immediate_update)
+{
+ (void)enc;
+ (void)enable;
+ (void)dsc_packed_pps;
+ (void)immediate_update;
+}
static const struct stream_encoder_funcs virtual_str_enc_funcs = {
.dp_set_odm_combine =
diff --git a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c
index 74962791302f..61553e24d53e 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c
@@ -525,6 +525,7 @@ static void split_stream_across_pipes(
struct pipe_ctx *primary_pipe,
struct pipe_ctx *secondary_pipe)
{
+ (void)res_ctx;
int pipe_idx = secondary_pipe->pipe_idx;
if (!primary_pipe->plane_state)
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c
index c5e84190c17a..5679b79d6f53 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c
@@ -76,7 +76,7 @@ struct _vcs_dpi_ip_params_st dcn1_0_ip = {
.line_buffer_size_bits = 589824,
.max_line_buffer_lines = 12,
.IsLineBufferBppFixed = 0,
- .LineBufferFixedBpp = -1,
+ .LineBufferFixedBpp = (unsigned int)-1,
.writeback_luma_buffer_size_kbytes = 12,
.writeback_chroma_buffer_size_kbytes = 8,
.max_num_dpp = 4,
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
index 7aaf13bbd4e4..887744d56d6a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
@@ -1316,6 +1316,7 @@ int dcn20_populate_dml_pipes_from_context(struct dc *dc,
display_e2e_pipe_params_st *pipes,
enum dc_validate_mode validate_mode)
{
+ (void)validate_mode;
int pipe_cnt, i;
bool synchronized_vblank = true;
struct resource_context *res_ctx = &context->res_ctx;
@@ -2335,7 +2336,7 @@ bool dcn21_validate_bandwidth_fp(struct dc *dc, struct dc_state *context,
/*Unsafe due to current pipe merge and split logic*/
ASSERT(context != dc->current_state);
- out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, validate_mode);
+ out = dcn21_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel, validate_mode, false);
if (pipe_cnt == 0)
goto validate_out;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
index 0c8c4a080c50..f5f636afe33c 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20.c
@@ -501,6 +501,8 @@ static bool CalculatePrefetchSchedule(
double *VUpdateWidthPix,
double *VReadyOffsetPix)
{
+ (void)mode_lib;
+
bool MyError = false;
unsigned int DPPCycles, DISPCLKCycles;
double DSTTotalPixelsAfterScaler, TotalRepeaterDelayTime;
@@ -878,6 +880,7 @@ static unsigned int CalculateVMAndRowBytes(
unsigned int *dpte_row_height,
unsigned int *meta_row_height)
{
+ (void)ViewportWidth;
unsigned int MetaRequestHeight;
unsigned int MetaRequestWidth;
unsigned int MetaSurfWidth;
@@ -2953,6 +2956,7 @@ static double CalculateRemoteSurfaceFlipDelay(
double *TInitXFill,
double *TslvChk)
{
+ (void)mode_lib;
double TSlvSetup, AvgfillRate, result;
*SrcActiveDrainRate = VRatio * SwathWidth * Bpp / LineTime;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
index c935903b68e1..95b0a3501880 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_mode_vba_20v2.c
@@ -495,6 +495,7 @@ static bool CalculateDelayAfterScaler(
double *DSTYAfterScaler
)
{
+ (void)ReturnBW;
unsigned int DPPCycles, DISPCLKCycles;
double DataFabricLineDeliveryTimeLuma;
double DataFabricLineDeliveryTimeChroma;
@@ -592,6 +593,8 @@ static bool CalculatePrefetchSchedule(
double *VUpdateWidthPix,
double *VReadyOffsetPix)
{
+ (void)mode_lib;
+
bool MyError = false;
double TotalRepeaterDelayTime;
double Tdm, LineTime, Tsetup;
@@ -938,6 +941,7 @@ static unsigned int CalculateVMAndRowBytes(
unsigned int *dpte_row_height,
unsigned int *meta_row_height)
{
+ (void)ViewportWidth;
unsigned int MetaRequestHeight;
unsigned int MetaRequestWidth;
unsigned int MetaSurfWidth;
@@ -3026,6 +3030,7 @@ static double CalculateRemoteSurfaceFlipDelay(
double *TInitXFill,
double *TslvChk)
{
+ (void)mode_lib;
double TSlvSetup, AvgfillRate, result;
*SrcActiveDrainRate = VRatio * SwathWidth * Bpp / LineTime;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
index 9c58ff1069d6..591d9618bdc0 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20.c
@@ -126,6 +126,7 @@ static double get_refcyc_per_delivery(struct display_mode_lib *mode_lib,
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -1538,6 +1539,9 @@ void dml20_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib,
const bool ignore_viewport_pos,
const bool immediate_flip_support)
{
+ (void)vm_en;
+ (void)ignore_viewport_pos;
+ (void)immediate_flip_support;
display_rq_params_st rq_param = {0};
display_dlg_sys_params_st dlg_sys_param = {0};
@@ -1588,6 +1592,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib,
unsigned int cur_width,
enum cursor_bpp cur_bpp)
{
+ (void)mode_lib;
unsigned int cur_src_width = cur_width;
unsigned int cur_req_size = 0;
unsigned int cur_req_width = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
index 570e6e39eb45..d4dddc9d535a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/display_rq_dlg_calc_20v2.c
@@ -126,6 +126,7 @@ static double get_refcyc_per_delivery(struct display_mode_lib *mode_lib,
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -1539,6 +1540,9 @@ void dml20v2_rq_dlg_get_dlg_reg(struct display_mode_lib *mode_lib,
const bool ignore_viewport_pos,
const bool immediate_flip_support)
{
+ (void)vm_en;
+ (void)ignore_viewport_pos;
+ (void)immediate_flip_support;
display_rq_params_st rq_param = {0};
display_dlg_sys_params_st dlg_sys_param = {0};
@@ -1589,6 +1593,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib,
unsigned int cur_width,
enum cursor_bpp cur_bpp)
{
+ (void)mode_lib;
unsigned int cur_src_width = cur_width;
unsigned int cur_req_size = 0;
unsigned int cur_req_width = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
index cd8cca651419..11570a0c9427 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_mode_vba_21.c
@@ -695,6 +695,9 @@ static bool CalculatePrefetchSchedule(
double *VUpdateWidthPix,
double *VReadyOffsetPix)
{
+ (void)mode_lib;
+ (void)XFCEnabled;
+
bool MyError = false;
unsigned int DPPCycles, DISPCLKCycles;
double DSTTotalPixelsAfterScaler, TotalRepeaterDelayTime;
@@ -1290,6 +1293,8 @@ static unsigned int CalculateVMAndRowBytes(
unsigned int *DPDE0BytesFrame,
unsigned int *MetaPTEBytesFrame)
{
+ (void)SourcePixelFormat;
+ (void)ViewportWidth;
unsigned int MPDEBytesFrame;
unsigned int DCCMetaSurfaceBytes;
unsigned int MacroTileSizeBytes;
@@ -3040,6 +3045,7 @@ static double CalculateRemoteSurfaceFlipDelay(
double *TInitXFill,
double *TslvChk)
{
+ (void)mode_lib;
double TSlvSetup, AvgfillRate, result;
*SrcActiveDrainRate = VRatio * SwathWidth * Bpp / LineTime;
@@ -3187,6 +3193,7 @@ static void CalculateFlipSchedule(
double *final_flip_bw,
bool *ImmediateFlipSupportedForPipe)
{
+ (void)mode_lib;
double min_row_time = 0.0;
unsigned int HostVMDynamicLevels;
double TimeForFetchingMetaPTEImmediateFlip;
@@ -5294,6 +5301,15 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
double *StutterEnterPlusExitWatermark,
double *MinActiveDRAMClockChangeLatencySupported)
{
+ (void)DPPCLK;
+ (void)SwathWidthSingleDPPY;
+ (void)DCFCLK;
+ (void)UrgentOutOfOrderReturn;
+ (void)ReturnBW;
+ (void)GPUVMEnable;
+ (void)dpte_group_bytes;
+ (void)MetaChunkSize;
+
double EffectiveLBLatencyHidingY;
double EffectiveLBLatencyHidingC;
double DPPOutputBufferLinesY;
@@ -5304,7 +5320,7 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
double LinesInDETC;
unsigned int LinesInDETYRoundedDownToSwath[DC__NUM_DPP__MAX];
unsigned int LinesInDETCRoundedDownToSwath;
- double FullDETBufferingTimeY[DC__NUM_DPP__MAX];
+ double FullDETBufferingTimeY[DC__NUM_DPP__MAX] = { 0 };
double FullDETBufferingTimeC;
double ActiveDRAMClockChangeLatencyMarginY;
double ActiveDRAMClockChangeLatencyMarginC;
@@ -5885,6 +5901,9 @@ static void CalculateMetaAndPTETimes(
double TimePerVMRequestVBlank[],
double TimePerVMRequestFlip[])
{
+ (void)VRatioPrefetchY;
+ (void)VRatioPrefetchC;
+
unsigned int meta_chunk_width;
unsigned int min_meta_chunk_width;
unsigned int meta_chunk_per_row_int;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
index f549da082c01..8a611b3bec33 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn21/display_rq_dlg_calc_21.c
@@ -102,6 +102,7 @@ static double get_refcyc_per_delivery(
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -1647,6 +1648,9 @@ void dml21_rq_dlg_get_dlg_reg(
const bool ignore_viewport_pos,
const bool immediate_flip_support)
{
+ (void)vm_en;
+ (void)ignore_viewport_pos;
+ (void)immediate_flip_support;
display_rq_params_st rq_param = {0};
display_dlg_sys_params_st dlg_sys_param = {0};
@@ -1702,6 +1706,7 @@ static void calculate_ttu_cursor(
unsigned int cur_width,
enum cursor_bpp cur_bpp)
{
+ (void)mode_lib;
unsigned int cur_src_width = cur_width;
unsigned int cur_req_size = 0;
unsigned int cur_req_width = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
index e5f5c0663750..0cdd60869ce1 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c
@@ -571,6 +571,7 @@ void dcn30_fpu_update_bw_bounding_box(struct dc *dc,
unsigned int *dcfclk_mhz,
unsigned int *dram_speed_mts)
{
+ (void)bw_params;
unsigned int i;
dc_assert_fp_enabled();
@@ -720,6 +721,7 @@ void dcn3_fpu_build_wm_range_table(struct clk_mgr *base)
void patch_dcn30_soc_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *dcn3_0_ip)
{
+ (void)dcn3_0_ip;
dc_assert_fp_enabled();
if (dc->ctx->dc_bios->funcs->get_soc_bb_info) {
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
index 1df3412be346..634982173190 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c
@@ -778,6 +778,8 @@ static bool CalculatePrefetchSchedule(
double *RequiredPrefetchPixDataBWChroma,
bool *NotEnoughTimeForDynamicMetadata)
{
+ (void)SwathWidthY;
+ (void)SwathWidthC;
struct vba_vars_st *v = &mode_lib->vba;
double DPPCLKDelaySubtotalPlusCNVCFormater = v->DPPCLKDelaySubtotal + v->DPPCLKDelayCNVCFormater;
bool MyError = false;
@@ -1233,6 +1235,10 @@ static void CalculateDCCConfiguration(
unsigned int *IndependentBlockLuma,
unsigned int *IndependentBlockChroma)
{
+ (void)SurfaceWidthChroma;
+ (void)SurfaceHeightChroma;
+ (void)BytePerPixelDETY;
+ (void)BytePerPixelDETC;
int yuv420 = 0;
int horz_div_l = 0;
int horz_div_c = 0;
@@ -1595,6 +1601,7 @@ static unsigned int CalculateVMAndRowBytes(
unsigned int *DPDE0BytesFrame,
unsigned int *MetaPTEBytesFrame)
{
+ (void)SourcePixelFormat;
unsigned int MPDEBytesFrame = 0;
unsigned int DCCMetaSurfaceBytes = 0;
unsigned int MacroTileSizeBytes = 0;
@@ -3068,6 +3075,8 @@ double dml30_CalculateWriteBackDISPCLK(
unsigned int HTotal,
unsigned int WritebackLineBufferSize)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackVRatio;
double DISPCLK_H = 0, DISPCLK_V = 0, DISPCLK_HB = 0;
DISPCLK_H = PixelClock * dml_ceil(WritebackHTaps / 8.0, 1) / WritebackHRatio;
@@ -3086,6 +3095,8 @@ static double CalculateWriteBackDelay(
long WritebackSourceHeight,
unsigned int HTotal)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackHRatio;
double CalculateWriteBackDelay = 0;
double Line_length = 0;
double Output_lines_last_notclamped = 0;
@@ -3199,6 +3210,8 @@ static void CalculateFlipSchedule(
double *final_flip_bw,
bool *ImmediateFlipSupportedForPipe)
{
+ (void)mode_lib;
+ (void)HostVMMinPageSize;
double min_row_time = 0.0;
unsigned int HostVMDynamicLevelsTrips = 0;
double TimeForFetchingMetaPTEImmediateFlip = 0;
@@ -4968,6 +4981,10 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
double BytePerPixelDETC[],
enum clock_change_support *DRAMClockChangeSupport)
{
+ (void)DCFCLK;
+ (void)ReturnBW;
+ (void)DPPCLK;
+ (void)DETBufferSizeC;
struct vba_vars_st *v = &mode_lib->vba;
double EffectiveLBLatencyHidingY = 0;
double EffectiveLBLatencyHidingC = 0;
@@ -5212,6 +5229,8 @@ static void CalculateUrgentBurstFactor(
double *UrgentBurstFactorChroma,
bool *NotEnoughUrgentLatencyHiding)
{
+ (void)DETBufferSizeInKByte;
+ (void)VRatioC;
double LinesInDETLuma = 0;
double LinesInDETChroma = 0;
unsigned int LinesInCursorBuffer = 0;
@@ -5575,6 +5594,8 @@ static void CalculateVMGroupAndRequestTimes(
double TimePerVMRequestVBlank[],
double TimePerVMRequestFlip[])
{
+ (void)dpte_row_width_luma_ub;
+ (void)dpte_row_width_chroma_ub;
int num_group_per_lower_vm_stage = 0;
int num_req_per_lower_vm_stage = 0;
unsigned int k;
@@ -5857,6 +5878,7 @@ static void CalculateSwathAndDETConfiguration(
bool ViewportSizeSupportPerPlane[],
bool *ViewportSizeSupport)
{
+ (void)HRatioChroma;
int MaximumSwathHeightY[DC__NUM_DPP__MAX] = { 0 };
int MaximumSwathHeightC[DC__NUM_DPP__MAX] = { 0 };
int MinimumSwathHeightY = 0;
@@ -6039,6 +6061,7 @@ static void CalculateSwathWidth(
unsigned int swath_width_luma_ub[],
unsigned int swath_width_chroma_ub[])
{
+ (void)BytePerPixY;
unsigned int k, j;
long surface_width_ub_l;
long surface_height_ub_l;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
index 4fb37df54d59..472ac5ee165f 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_rq_dlg_calc_30.c
@@ -50,6 +50,7 @@ static double get_refcyc_per_delivery(struct display_mode_lib *mode_lib,
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -804,6 +805,7 @@ static void calculate_ttu_cursor(struct display_mode_lib *mode_lib,
unsigned int cur_width,
enum cursor_bpp cur_bpp)
{
+ (void)mode_lib;
unsigned int cur_src_width = cur_width;
unsigned int cur_req_size = 0;
unsigned int cur_req_width = 0;
@@ -896,6 +898,9 @@ static void dml_rq_dlg_get_dlg_params(struct display_mode_lib *mode_lib,
const bool ignore_viewport_pos,
const bool immediate_flip_support)
{
+ (void)vm_en;
+ (void)ignore_viewport_pos;
+ (void)immediate_flip_support;
const display_pipe_source_params_st *src = &e2e_pipe_param[pipe_idx].pipe.src;
const display_pipe_dest_params_st *dst = &e2e_pipe_param[pipe_idx].pipe.dest;
const display_output_params_st *dout = &e2e_pipe_param[pipe_idx].dout;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
index ed59c77bc6f6..9833467722b9 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
@@ -873,6 +873,11 @@ static bool CalculatePrefetchSchedule(
double *VUpdateWidthPix,
double *VReadyOffsetPix)
{
+ (void)mode_lib;
+ (void)HostVMMinPageSize;
+ (void)SwathWidthY;
+ (void)SwathWidthC;
+
bool MyError = false;
unsigned int DPPCycles, DISPCLKCycles;
double DSTTotalPixelsAfterScaler;
@@ -1491,6 +1496,10 @@ static void CalculateDCCConfiguration(
unsigned int *IndependentBlockLuma,
unsigned int *IndependentBlockChroma)
{
+ (void)SurfaceWidthChroma;
+ (void)SurfaceHeightChroma;
+ (void)BytePerPixelDETY;
+ (void)BytePerPixelDETC;
int yuv420;
int horz_div_l;
int horz_div_c;
@@ -1823,6 +1832,7 @@ static unsigned int CalculateVMAndRowBytes(
int *DPDE0BytesFrame,
int *MetaPTEBytesFrame)
{
+ (void)SourcePixelFormat;
struct vba_vars_st *v = &mode_lib->vba;
unsigned int MPDEBytesFrame;
unsigned int DCCMetaSurfaceBytes;
@@ -3365,6 +3375,8 @@ double dml31_CalculateWriteBackDISPCLK(
unsigned int HTotal,
unsigned int WritebackLineBufferSize)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackVRatio;
double DISPCLK_H, DISPCLK_V, DISPCLK_HB;
DISPCLK_H = PixelClock * dml_ceil(WritebackHTaps / 8.0, 1) / WritebackHRatio;
@@ -3383,6 +3395,8 @@ static double CalculateWriteBackDelay(
int WritebackSourceHeight,
unsigned int HTotal)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackHRatio;
double CalculateWriteBackDelay;
double Line_length;
double Output_lines_last_notclamped;
@@ -5566,6 +5580,9 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
double *Z8StutterExitWatermark,
double *Z8StutterEnterPlusExitWatermark)
{
+ (void)DCFCLK;
+ (void)ReturnBW;
+ (void)DETBufferSizeC;
struct vba_vars_st *v = &mode_lib->vba;
double EffectiveLBLatencyHidingY;
double EffectiveLBLatencyHidingC;
@@ -5831,6 +5848,7 @@ static void CalculateUrgentBurstFactor(
double *UrgentBurstFactorChroma,
bool *NotEnoughUrgentLatencyHiding)
{
+ (void)VRatioC;
double LinesInDETLuma;
double LinesInDETChroma;
unsigned int LinesInCursorBuffer;
@@ -6213,6 +6231,8 @@ static void CalculateVMGroupAndRequestTimes(
double TimePerVMRequestVBlank[],
double TimePerVMRequestFlip[])
{
+ (void)dpte_row_width_luma_ub;
+ (void)dpte_row_width_chroma_ub;
int num_group_per_lower_vm_stage;
int num_req_per_lower_vm_stage;
int k;
@@ -6350,6 +6370,8 @@ static void CalculateStutterEfficiency(
int *Z8NumberOfStutterBurstsPerFrame,
double *StutterPeriod)
{
+ (void)ConfigReturnBufferSizeInKByte;
+
struct vba_vars_st *v = &mode_lib->vba;
double DETBufferingTimeY;
@@ -6649,6 +6671,7 @@ static void CalculateSwathAndDETConfiguration(
bool ViewportSizeSupportPerPlane[],
bool *ViewportSizeSupport)
{
+ (void)HRatioChroma;
int MaximumSwathHeightY[DC__NUM_DPP__MAX];
int MaximumSwathHeightC[DC__NUM_DPP__MAX];
int MinimumSwathHeightY;
@@ -6823,6 +6846,7 @@ static void CalculateSwathWidth(
int swath_width_luma_ub[],
int swath_width_chroma_ub[])
{
+ (void)BytePerPixY;
enum odm_combine_mode MainPlaneODMCombine;
int j, k;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c
index bfeb01477f0c..dfa1bc31eb0a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_rq_dlg_calc_31.c
@@ -51,6 +51,7 @@ static double get_refcyc_per_delivery(
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -785,6 +786,7 @@ static void calculate_ttu_cursor(
unsigned int cur_width,
enum cursor_bpp cur_bpp)
{
+ (void)mode_lib;
unsigned int cur_src_width = cur_width;
unsigned int cur_req_size = 0;
unsigned int cur_req_width = 0;
@@ -859,6 +861,12 @@ static void dml_rq_dlg_get_dlg_params(
const bool ignore_viewport_pos,
const bool immediate_flip_support)
{
+ (void)cstate_en;
+ (void)pstate_en;
+ (void)vm_en;
+ (void)ignore_viewport_pos;
+ (void)immediate_flip_support;
+ (void)dlg_sys_param;
const display_pipe_source_params_st *src = &e2e_pipe_param[pipe_idx].pipe.src;
const display_pipe_dest_params_st *dst = &e2e_pipe_param[pipe_idx].pipe.dest;
const display_clocks_and_cfg_st *clks = &e2e_pipe_param[pipe_idx].clks_cfg;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c
index df9d50b9b57c..ab016c294ba7 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c
@@ -391,13 +391,9 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c
}
context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_14_DEFAULT_DET_SIZE;
- dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state
&& pipe->plane_state->rotation == ROTATION_ANGLE_0 && !dc->debug.disable_z9_mpc) {
- if (is_dual_plane(pipe->plane_state->format)
- && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) {
- dc->config.enable_4to1MPC = true;
- } else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) {
+ if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) {
/* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */
context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192;
pipes[0].pipe.src.unbounded_req_mode = true;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
index 9f3938a50240..033fde774337 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c
@@ -891,6 +891,11 @@ static bool CalculatePrefetchSchedule(
double *VUpdateWidthPix,
double *VReadyOffsetPix)
{
+ (void)mode_lib;
+ (void)HostVMMinPageSize;
+ (void)SwathWidthY;
+ (void)SwathWidthC;
+
bool MyError = false;
unsigned int DPPCycles, DISPCLKCycles;
double DSTTotalPixelsAfterScaler;
@@ -1508,6 +1513,10 @@ static void CalculateDCCConfiguration(
unsigned int *IndependentBlockLuma,
unsigned int *IndependentBlockChroma)
{
+ (void)SurfaceWidthChroma;
+ (void)SurfaceHeightChroma;
+ (void)BytePerPixelDETY;
+ (void)BytePerPixelDETC;
int yuv420;
int horz_div_l;
int horz_div_c;
@@ -1840,6 +1849,7 @@ static unsigned int CalculateVMAndRowBytes(
int *DPDE0BytesFrame,
int *MetaPTEBytesFrame)
{
+ (void)SourcePixelFormat;
struct vba_vars_st *v = &mode_lib->vba;
unsigned int MPDEBytesFrame;
unsigned int DCCMetaSurfaceBytes;
@@ -3471,6 +3481,8 @@ double dml314_CalculateWriteBackDISPCLK(
unsigned int HTotal,
unsigned int WritebackLineBufferSize)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackVRatio;
double DISPCLK_H, DISPCLK_V, DISPCLK_HB;
DISPCLK_H = PixelClock * dml_ceil(WritebackHTaps / 8.0, 1) / WritebackHRatio;
@@ -3489,6 +3501,8 @@ static double CalculateWriteBackDelay(
int WritebackSourceHeight,
unsigned int HTotal)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackHRatio;
double CalculateWriteBackDelay;
double Line_length;
double Output_lines_last_notclamped;
@@ -5660,6 +5674,9 @@ static void CalculateWatermarksAndDRAMSpeedChangeSupport(
double *Z8StutterExitWatermark,
double *Z8StutterEnterPlusExitWatermark)
{
+ (void)DCFCLK;
+ (void)ReturnBW;
+ (void)DETBufferSizeC;
struct vba_vars_st *v = &mode_lib->vba;
double EffectiveLBLatencyHidingY;
double EffectiveLBLatencyHidingC;
@@ -5925,6 +5942,7 @@ static void CalculateUrgentBurstFactor(
double *UrgentBurstFactorChroma,
bool *NotEnoughUrgentLatencyHiding)
{
+ (void)VRatioC;
double LinesInDETLuma;
double LinesInDETChroma;
unsigned int LinesInCursorBuffer;
@@ -6308,6 +6326,8 @@ static void CalculateVMGroupAndRequestTimes(
double TimePerVMRequestVBlank[],
double TimePerVMRequestFlip[])
{
+ (void)dpte_row_width_luma_ub;
+ (void)dpte_row_width_chroma_ub;
int num_group_per_lower_vm_stage;
int num_req_per_lower_vm_stage;
int k;
@@ -6445,6 +6465,8 @@ static void CalculateStutterEfficiency(
int *Z8NumberOfStutterBurstsPerFrame,
double *StutterPeriod)
{
+ (void)ConfigReturnBufferSizeInKByte;
+
struct vba_vars_st *v = &mode_lib->vba;
double DETBufferingTimeY;
@@ -6743,6 +6765,7 @@ static void CalculateSwathAndDETConfiguration(
bool ViewportSizeSupportPerPlane[],
bool *ViewportSizeSupport)
{
+ (void)HRatioChroma;
int MaximumSwathHeightY[DC__NUM_DPP__MAX];
int MaximumSwathHeightC[DC__NUM_DPP__MAX];
int MinimumSwathHeightY;
@@ -6914,6 +6937,7 @@ static void CalculateSwathWidth(
int swath_width_luma_ub[],
int swath_width_chroma_ub[])
{
+ (void)BytePerPixY;
enum odm_combine_mode MainPlaneODMCombine;
int j, k;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c
index 04df263ff65e..40a916c2a9c6 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn314/display_rq_dlg_calc_314.c
@@ -139,6 +139,7 @@ static double get_refcyc_per_delivery(
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -872,6 +873,7 @@ static void calculate_ttu_cursor(
unsigned int cur_width,
enum cursor_bpp cur_bpp)
{
+ (void)mode_lib;
unsigned int cur_src_width = cur_width;
unsigned int cur_req_size = 0;
unsigned int cur_req_width = 0;
@@ -944,6 +946,12 @@ static void dml_rq_dlg_get_dlg_params(
const bool ignore_viewport_pos,
const bool immediate_flip_support)
{
+ (void)cstate_en;
+ (void)pstate_en;
+ (void)vm_en;
+ (void)ignore_viewport_pos;
+ (void)immediate_flip_support;
+ (void)dlg_sys_param;
const display_pipe_source_params_st *src = &e2e_pipe_param[pipe_idx].pipe.src;
const display_pipe_dest_params_st *dst = &e2e_pipe_param[pipe_idx].pipe.dest;
const display_clocks_and_cfg_st *clks = &e2e_pipe_param[pipe_idx].clks_cfg;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
index 8a0f128722b0..e29497204df7 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
@@ -3488,6 +3488,7 @@ bool dcn32_allow_subvp_high_refresh_rate(struct dc *dc, struct dc_state *context
*/
double dcn32_determine_max_vratio_prefetch(struct dc *dc, struct dc_state *context)
{
+ (void)dc;
double max_vratio_pre = __DML_MAX_BW_RATIO_PRE__; // Default value is 4
int i;
@@ -3593,6 +3594,7 @@ bool dcn32_find_vactive_pipe(struct dc *dc, const struct dc_state *context, stru
void dcn32_set_clock_limits(const struct _vcs_dpi_soc_bounding_box_st *soc_bb)
{
+ (void)soc_bb;
dc_assert_fp_enabled();
dcn3_2_soc.clock_limits[0].dcfclk_mhz = 1200.0;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
index 0748ef36a16a..5e72966a8daf 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c
@@ -457,10 +457,11 @@ void dml32_CalculateSwathAndDETConfiguration(
bool ViewportSizeSupportPerSurface[],
bool *ViewportSizeSupport)
{
+ (void)HRatioChroma;
unsigned int MaximumSwathHeightY[DC__NUM_DPP__MAX];
unsigned int MaximumSwathHeightC[DC__NUM_DPP__MAX];
- unsigned int RoundedUpMaxSwathSizeBytesY[DC__NUM_DPP__MAX];
- unsigned int RoundedUpMaxSwathSizeBytesC[DC__NUM_DPP__MAX];
+ unsigned int RoundedUpMaxSwathSizeBytesY[DC__NUM_DPP__MAX] = { 0 };
+ unsigned int RoundedUpMaxSwathSizeBytesC[DC__NUM_DPP__MAX] = { 0 };
unsigned int RoundedUpSwathSizeBytesY;
unsigned int RoundedUpSwathSizeBytesC;
double SwathWidthdoubleDPP[DC__NUM_DPP__MAX];
@@ -716,6 +717,7 @@ void dml32_CalculateSwathWidth(
unsigned int swath_width_luma_ub[], // per-pipe
unsigned int swath_width_chroma_ub[]) // per-pipe
{
+ (void)BytePerPixY;
unsigned int k, j;
enum odm_combine_mode MainSurfaceODMMode;
@@ -2304,6 +2306,7 @@ unsigned int dml32_CalculateVMAndRowBytes(
unsigned int *DPDE0BytesFrame,
unsigned int *MetaPTEBytesFrame)
{
+ (void)SourcePixelFormat;
unsigned int MPDEBytesFrame;
unsigned int DCCMetaSurfaceBytes;
unsigned int ExtraDPDEBytesFrame;
@@ -2745,6 +2748,7 @@ void dml32_CalculateUrgentBurstFactor(
double *UrgentBurstFactorChroma,
bool *NotEnoughUrgentLatencyHiding)
{
+ (void)VRatioC;
double LinesInDETLuma;
double LinesInDETChroma;
unsigned int LinesInCursorBuffer;
@@ -2900,6 +2904,8 @@ double dml32_CalculateWriteBackDelay(
unsigned int WritebackSourceHeight,
unsigned int HTotal)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackHRatio;
double CalculateWriteBackDelay;
double Line_length;
double Output_lines_last_notclamped;
@@ -2977,6 +2983,9 @@ void dml32_UseMinimumDCFCLK(
/* Output */
double DCFCLKState[][2])
{
+ (void)MaxAveragePercentOfIdealSDPPortBWDisplayCanUseInNormalSystemOperation;
+ (void)ReadBandwidthLuma;
+ (void)ReadBandwidthChroma;
unsigned int i, j, k;
unsigned int dummy1;
double dummy2, dummy3;
@@ -2988,7 +2997,7 @@ void dml32_UseMinimumDCFCLK(
for (j = 0; j <= 1; ++j) {
double PixelDCFCLKCyclesRequiredInPrefetch[DC__NUM_DPP__MAX];
double PrefetchPixelLinesTime[DC__NUM_DPP__MAX];
- double DCFCLKRequiredForPeakBandwidthPerSurface[DC__NUM_DPP__MAX];
+ double DCFCLKRequiredForPeakBandwidthPerSurface[DC__NUM_DPP__MAX] = { 0 };
double DynamicMetadataVMExtraLatency[DC__NUM_DPP__MAX];
double MinimumTWait = 0.0;
double DPTEBandwidth;
@@ -3447,6 +3456,8 @@ bool dml32_CalculatePrefetchSchedule(
double *VUpdateWidthPix,
double *VReadyOffsetPix)
{
+ (void)SwathWidthY;
+ (void)SwathWidthC;
double DPPCLKDelaySubtotalPlusCNVCFormater = v->DPPCLKDelaySubtotal + v->DPPCLKDelayCNVCFormater;
bool MyError = false;
unsigned int DPPCycles, DISPCLKCycles;
@@ -4145,6 +4156,7 @@ void dml32_CalculateFlipSchedule(
double *final_flip_bw,
bool *ImmediateFlipSupportedForPipe)
{
+ (void)HostVMMinPageSize;
double min_row_time = 0.0;
unsigned int HostVMDynamicLevelsTrips;
double TimeForFetchingMetaPTEImmediateFlip;
@@ -4287,6 +4299,8 @@ void dml32_CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport(
bool *USRRetrainingSupport,
double ActiveDRAMClockChangeLatencyMargin[])
{
+ (void)DCFCLK;
+ (void)ReturnBW;
unsigned int i, j, k;
unsigned int SurfaceWithMinActiveFCLKChangeMargin = 0;
unsigned int DRAMClockChangeSupportNumber = 0;
@@ -4655,6 +4669,8 @@ double dml32_CalculateWriteBackDISPCLK(
unsigned int WritebackLineBufferSize,
double DISPCLKDPPCLKVCOSpeed)
{
+ (void)WritebackPixelFormat;
+ (void)WritebackVRatio;
double DISPCLK_H, DISPCLK_V, DISPCLK_HB;
DISPCLK_H = PixelClock * dml_ceil(WritebackHTaps / 8.0, 1) / WritebackHRatio;
@@ -5166,6 +5182,8 @@ void dml32_CalculateVMGroupAndRequestTimes(
double TimePerVMRequestVBlank[],
double TimePerVMRequestFlip[])
{
+ (void)dpte_row_width_luma_ub;
+ (void)dpte_row_width_chroma_ub;
unsigned int k;
unsigned int num_group_per_lower_vm_stage;
unsigned int num_req_per_lower_vm_stage;
@@ -5321,6 +5339,11 @@ void dml32_CalculateDCCConfiguration(
unsigned int *IndependentBlockLuma,
unsigned int *IndependentBlockChroma)
{
+ (void)SurfaceWidthChroma;
+ (void)SurfaceHeightChroma;
+ (void)TilingFormat;
+ (void)BytePerPixelDETY;
+ (void)BytePerPixelDETC;
typedef enum {
REQ_256Bytes,
REQ_128BytesNonContiguous,
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
index 8a177d5ae213..7f40048dd67d 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c
@@ -202,6 +202,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_5_soc = {
void dcn35_build_wm_range_table_fpu(struct clk_mgr *clk_mgr)
{
+ (void)clk_mgr;
//TODO
}
@@ -528,14 +529,9 @@ int dcn35_populate_dml_pipes_from_context_fpu(struct dc *dc,
}
context->bw_ctx.dml.ip.det_buffer_size_kbytes = 384;/*per guide*/
- dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
- if (is_dual_plane(pipe->plane_state->format)
- && pipe->plane_state->src_rect.width <= 1920 &&
- pipe->plane_state->src_rect.height <= 1080) {
- dc->config.enable_4to1MPC = true;
- } else if (!is_dual_plane(pipe->plane_state->format) &&
+ if (!is_dual_plane(pipe->plane_state->format) &&
pipe->plane_state->src_rect.width <= 5120) {
/*
* Limit to 5k max to avoid forced pipe split when there
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 77023b619f1e..73c2aee57f28 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
@@ -561,14 +561,9 @@ int dcn351_populate_dml_pipes_from_context_fpu(struct dc *dc,
}
context->bw_ctx.dml.ip.det_buffer_size_kbytes = 384;/*per guide*/
- dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
- if (is_dual_plane(pipe->plane_state->format)
- && pipe->plane_state->src_rect.width <= 1920 &&
- pipe->plane_state->src_rect.height <= 1080) {
- dc->config.enable_4to1MPC = true;
- } else if (!is_dual_plane(pipe->plane_state->format) &&
+ if (!is_dual_plane(pipe->plane_state->format) &&
pipe->plane_state->src_rect.width <= 5120) {
/*
* Limit to 5k max to avoid forced pipe split when there
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c
index da0cfbb071e6..684779ee54a3 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_lib.c
@@ -162,6 +162,7 @@ void dml_log_pipe_params(
display_e2e_pipe_params_st *pipes,
int pipe_cnt)
{
+ (void)mode_lib;
display_pipe_source_params_st *pipe_src;
display_pipe_dest_params_st *pipe_dest;
scaler_ratio_depth_st *scale_ratio_depth;
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c
index 12ff65b6a7e5..3f27293a41cb 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_rq_dlg_helpers.c
@@ -49,6 +49,8 @@ void print__rq_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dp
void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_sizing_params_st *rq_sizing)
{
+ (void)mode_lib;
+ (void)rq_sizing;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_SIZING_PARAM_ST\n");
dml_print("DML_RQ_DLG_CALC: chunk_bytes = %0d\n", rq_sizing->chunk_bytes);
@@ -64,6 +66,8 @@ void print__data_rq_sizing_params_st(struct display_mode_lib *mode_lib, const st
void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_dlg_params_st *rq_dlg_param)
{
+ (void)mode_lib;
+ (void)rq_dlg_param;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_DLG_PARAM_ST\n");
dml_print(
@@ -107,6 +111,8 @@ void print__data_rq_dlg_params_st(struct display_mode_lib *mode_lib, const struc
void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_misc_params_st *rq_misc_param)
{
+ (void)mode_lib;
+ (void)rq_misc_param;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_MISC_PARAM_ST\n");
dml_print(
@@ -124,6 +130,8 @@ void print__data_rq_misc_params_st(struct display_mode_lib *mode_lib, const stru
void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_dlg_sys_params_st *dlg_sys_param)
{
+ (void)dlg_sys_param;
+ (void)mode_lib;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_RQ_DLG_PARAM_ST\n");
dml_print("DML_RQ_DLG_CALC: t_mclk_wm_us = %3.2f\n", dlg_sys_param->t_mclk_wm_us);
@@ -144,6 +152,8 @@ void print__dlg_sys_params_st(struct display_mode_lib *mode_lib, const struct _v
void print__data_rq_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_data_rq_regs_st *rq_regs)
{
+ (void)mode_lib;
+ (void)rq_regs;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_DATA_RQ_REGS_ST\n");
dml_print("DML_RQ_DLG_CALC: chunk_size = 0x%0x\n", rq_regs->chunk_size);
@@ -179,6 +189,8 @@ void print__rq_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_
void print__dlg_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_dlg_regs_st *dlg_regs)
{
+ (void)dlg_regs;
+ (void)mode_lib;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_DLG_REGS_ST\n");
dml_print(
@@ -316,6 +328,8 @@ void print__dlg_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi
void print__ttu_regs_st(struct display_mode_lib *mode_lib, const struct _vcs_dpi_display_ttu_regs_st *ttu_regs)
{
+ (void)mode_lib;
+ (void)ttu_regs;
dml_print("DML_RQ_DLG_CALC: =====================================\n");
dml_print("DML_RQ_DLG_CALC: DISPLAY_TTU_REGS_ST\n");
dml_print(
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
index 88dc2b97e7bf..cf194bcba455 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dml1_display_rq_dlg_calc.c
@@ -104,6 +104,7 @@ static double get_refcyc_per_delivery(
unsigned int delivery_width,
unsigned int req_per_swath_ub)
{
+ (void)mode_lib;
double refcyc_per_delivery = 0.0;
if (vratio <= 1.0) {
@@ -133,6 +134,7 @@ static double get_vratio_pre(
double vinit,
double l_sw)
{
+ (void)mode_lib;
double prefill = dml_floor(vinit, 1);
double vratio_pre = 1.0;
@@ -174,6 +176,7 @@ static void get_swath_need(
unsigned int swath_height,
double vinit)
{
+ (void)mode_lib;
double prefill = dml_floor(vinit, 1);
unsigned int max_partial_sw_int;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
index 30cfc0848792..2625943d7f7e 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/Makefile
@@ -53,25 +53,29 @@ 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/
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_util.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper_fpu.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_utils.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_policy.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_translation_helper.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_mall_phantom.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml_display_rq_dlg_calc.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_dc_resource_mgmt.o := $(dml2_ccflags)
+# 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
+DML2_ABS_PATH := $(FULL_AMD_DISPLAY_PATH)/dc/dml2_0
+DML2_C_FILES := $(shell find $(DML2_ABS_PATH) -name '*.c' -type f)
+
+# FPU flags step 2: Convert to .o and make paths relative to $(AMDDALPATH)/dc/dml2_0/
+DML2_RELATIVE_O_FILES := $(patsubst $(DML2_ABS_PATH)/%,dc/dml2_0/%,$(patsubst %.c,%.o,$(DML2_C_FILES)))
+# FPU flags step 3: Apply FPU flags to all .o files from dal/dc/dml2_0 and it's subfolders
+$(foreach obj,$(DML2_RELATIVE_O_FILES),$(eval CFLAGS_$(AMDDALPATH)/$(obj) := $(dml2_ccflags)))
+$(foreach obj,$(DML2_RELATIVE_O_FILES),$(eval CFLAGS_REMOVE_$(AMDDALPATH)/$(obj) := $(dml2_rcflags)))
+
+# FPU flags step 4: Replace CFLAGS per file for files with additional flags beyond dml2_ccflags and dml2_rcflags
+CFLAGS_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag)
+CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_ccflags) $(frame_warn_flag)
+CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_ccflags) $(frame_warn_flag)
+CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper.o := $(dml2_rcflags)
+CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_wrapper.o := $(dml2_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/display_mode_core.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/display_mode_util.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper_fpu.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_utils.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_policy.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_translation_helper.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_mall_phantom.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml_display_rq_dlg_calc.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_dc_resource_mgmt.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml2_wrapper.o := $(dml2_ccflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_wrapper.o := $(dml2_ccflags)
DML2 = display_mode_core.o display_mode_util.o dml2_wrapper_fpu.o dml2_wrapper.o \
dml2_utils.o dml2_policy.o dml2_translation_helper.o dml2_dc_resource_mgmt.o dml2_mall_phantom.o \
@@ -81,39 +85,6 @@ AMD_DAL_DML2 = $(addprefix $(AMDDALPATH)/dc/dml2_0/,$(DML2))
AMD_DISPLAY_FILES += $(AMD_DAL_DML2)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_ccflags) $(frame_warn_flag)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_ccflags) $(frame_warn_flag)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_standalone_libraries/lib_float_math.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_translation_helper.o := $(dml2_ccflags)
-CFLAGS_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_utils.o := $(dml2_ccflags)
-
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_factory.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_interfaces.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_top/dml2_top_soc15.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_factory.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_factory.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/src/dml2_standalone_libraries/lib_float_math.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_translation_helper.o := $(dml2_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2_0/dml21/dml21_utils.o := $(dml2_rcflags)
DML21 := src/dml2_top/dml2_top_interfaces.o
DML21 += src/dml2_top/dml2_top_soc15.o
@@ -124,6 +95,7 @@ DML21 += src/dml2_core/dml2_core_dcn4_calcs.o
DML21 += src/dml2_dpmm/dml2_dpmm_dcn4.o
DML21 += src/dml2_dpmm/dml2_dpmm_factory.o
DML21 += src/dml2_mcg/dml2_mcg_dcn4.o
+DML21 += src/dml2_mcg/dml2_mcg_dcn42.o
DML21 += src/dml2_mcg/dml2_mcg_factory.o
DML21 += src/dml2_pmo/dml2_pmo_dcn3.o
DML21 += src/dml2_pmo/dml2_pmo_factory.o
@@ -131,6 +103,7 @@ DML21 += src/dml2_pmo/dml2_pmo_dcn4_fams2.o
DML21 += src/dml2_standalone_libraries/lib_float_math.o
DML21 += dml21_translation_helper.o
DML21 += dml21_wrapper.o
+DML21 += dml21_wrapper_fpu.o
DML21 += dml21_utils.o
AMD_DAL_DML21 = $(addprefix $(AMDDALPATH)/dc/dml2_0/dml21/,$(DML21))
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/display_mode_core.c b/drivers/gpu/drm/amd/display/dc/dml2_0/display_mode_core.c
index 09303c282495..8e8935995fca 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/display_mode_core.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/display_mode_core.c
@@ -4089,8 +4089,8 @@ static void CalculateSwathAndDETConfiguration(struct display_mode_lib_scratch_st
dml_uint_t MaximumSwathHeightC[__DML_NUM_PLANES__];
dml_uint_t RoundedUpMaxSwathSizeBytesY[__DML_NUM_PLANES__];
dml_uint_t RoundedUpMaxSwathSizeBytesC[__DML_NUM_PLANES__];
- dml_uint_t RoundedUpSwathSizeBytesY[__DML_NUM_PLANES__];
- dml_uint_t RoundedUpSwathSizeBytesC[__DML_NUM_PLANES__];
+ dml_uint_t RoundedUpSwathSizeBytesY[__DML_NUM_PLANES__] = { 0 };
+ dml_uint_t RoundedUpSwathSizeBytesC[__DML_NUM_PLANES__] = { 0 };
dml_uint_t SwathWidthSingleDPP[__DML_NUM_PLANES__];
dml_uint_t SwathWidthSingleDPPChroma[__DML_NUM_PLANES__];
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 bf5e7f4e0416..2f0e0048bea8 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
@@ -45,6 +45,9 @@ static enum dml2_project_id dml21_dcn_revision_to_dml2_project_id(enum dce_versi
case DCN_VERSION_4_01:
project_id = dml2_project_dcn4x_stage2_auto_drr_svp;
break;
+ case DCN_VERSION_4_2:
+ project_id = dml2_project_dcn42;
+ break;
default:
project_id = dml2_project_invalid;
DC_ERR("unsupported dcn version for DML21!");
@@ -87,7 +90,8 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf
struct pipe_ctx *pipe_ctx,
struct dml2_context *dml_ctx)
{
- unsigned int hblank_start, vblank_start, min_hardware_refresh_in_uhz;
+ unsigned int hblank_start, vblank_start;
+ uint64_t min_hardware_refresh_in_uhz;
uint32_t pix_clk_100hz;
timing->h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right + pipe_ctx->dsc_padding_params.dsc_hactive_padding;
@@ -102,7 +106,7 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf
timing->h_total = stream->timing.h_total + pipe_ctx->dsc_padding_params.dsc_htotal_padding;
timing->v_total = stream->timing.v_total;
timing->h_sync_width = stream->timing.h_sync_width;
- timing->interlaced = stream->timing.flags.INTERLACE;
+ timing->interlaced = (stream->timing.flags.INTERLACE != 0);
hblank_start = stream->timing.h_total - stream->timing.h_front_porch;
@@ -134,7 +138,11 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf
(timing->h_total * (long long)calc_max_hardware_v_total(stream)));
}
- timing->drr_config.min_refresh_uhz = max(stream->timing.min_refresh_in_uhz, min_hardware_refresh_in_uhz);
+ {
+ uint64_t min_refresh = max((uint64_t)stream->timing.min_refresh_in_uhz, min_hardware_refresh_in_uhz);
+ ASSERT(min_refresh <= ULONG_MAX);
+ timing->drr_config.min_refresh_uhz = (unsigned long)min_refresh;
+ }
if (dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase &&
stream->ctx->dc->config.enable_fpo_flicker_detection == 1)
@@ -615,12 +623,20 @@ static void populate_dml21_plane_config_from_plane_state(struct dml2_context *dm
case DC_CM2_GPU_MEM_SIZE_171717:
plane->tdlut.tdlut_width_mode = dml2_tdlut_width_17_cube;
break;
+ case DC_CM2_GPU_MEM_SIZE_333333:
+ plane->tdlut.tdlut_width_mode = dml2_tdlut_width_33_cube;
+ break;
+ // handling when use case and HW support available
+ case DC_CM2_GPU_MEM_SIZE_454545:
+ case DC_CM2_GPU_MEM_SIZE_656565:
+ break;
case DC_CM2_GPU_MEM_SIZE_TRANSFORMED:
default:
//plane->tdlut.tdlut_width_mode = dml2_tdlut_width_flatten; // dml2_tdlut_width_flatten undefined
break;
}
}
+
plane->tdlut.setup_for_tdlut |= dml_ctx->config.force_tdlut_enable;
plane->dynamic_meta_data.enable = false;
@@ -686,7 +702,7 @@ unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx,
if (!dml21_wrapper_get_plane_id(context, stream_id, plane, &plane_id)) {
ASSERT(false);
- return -1;
+ return UINT_MAX;
}
for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
@@ -734,8 +750,12 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s
memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
dml_dispcfg->gpuvm_enable = dml_ctx->config.gpuvm_enable;
- dml_dispcfg->gpuvm_max_page_table_levels = 4;
- dml_dispcfg->hostvm_enable = false;
+ if (dml_ctx->v21.dml_init.soc_bb.gpuvm_max_page_table_levels)
+ dml_dispcfg->gpuvm_max_page_table_levels = dml_ctx->v21.dml_init.soc_bb.gpuvm_max_page_table_levels;
+ else
+ dml_dispcfg->gpuvm_max_page_table_levels = 4;
+ dml_dispcfg->hostvm_enable = dml_ctx->config.hostvm_enable;
+ dml_dispcfg->hostvm_max_non_cached_page_table_levels = dml_ctx->v21.dml_init.soc_bb.hostvm_max_non_cached_page_table_levels;
dml_dispcfg->minimize_det_reallocation = true;
dml_dispcfg->overrides.enable_subvp_implicit_pmo = true;
@@ -820,6 +840,9 @@ void dml21_copy_clocks_to_dc_state(struct dml2_context *in_ctx, struct dc_state
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.stutter_efficiency.base_efficiency = in_ctx->v21.mode_programming.programming->stutter.base_percent_efficiency;
context->bw_ctx.bw.dcn.clk.stutter_efficiency.low_power_efficiency = in_ctx->v21.mode_programming.programming->stutter.low_power_percent_efficiency;
+ context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_efficiency = in_ctx->v21.mode_programming.programming->informative.power_management.z8.stutter_efficiency;
+ context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_period = in_ctx->v21.mode_programming.programming->informative.power_management.z8.stutter_period;
+ context->bw_ctx.bw.dcn.clk.zstate_support = in_ctx->v21.mode_programming.programming->z8_stutter.supported_in_blank; /*ignore meets_eco since it is not used*/
}
static struct dml2_dchub_watermark_regs *wm_set_index_to_dc_wm_set(union dcn_watermark_set *watermarks, const enum dml2_dchub_watermark_reg_set_index wm_index)
@@ -927,3 +950,31 @@ void dml21_set_dc_p_state_type(
}
}
+void dml21_init_min_clocks_for_dc_state(struct dml2_context *in_ctx, struct dc_state *context)
+{
+ unsigned int lowest_dpm_state_index = 0;
+ struct dc_clocks *min_clocks = &context->bw_ctx.bw.dcn.clk;
+
+ min_clocks->dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[lowest_dpm_state_index];
+ min_clocks->dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[lowest_dpm_state_index];
+ min_clocks->dcfclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dcfclk.clk_values_khz[lowest_dpm_state_index];
+ min_clocks->dramclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.uclk.clk_values_khz[lowest_dpm_state_index];
+ min_clocks->fclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.fclk.clk_values_khz[lowest_dpm_state_index];
+ min_clocks->idle_dramclk_khz = 0;
+ min_clocks->idle_fclk_khz = 0;
+ min_clocks->dcfclk_deep_sleep_khz = 0;
+ min_clocks->fclk_p_state_change_support = true;
+ min_clocks->p_state_change_support = true;
+ min_clocks->dtbclk_en = false;
+ min_clocks->ref_dtbclk_khz = 0;
+ min_clocks->socclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.socclk.clk_values_khz[lowest_dpm_state_index];
+ 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->stutter_efficiency.base_efficiency = 1;
+ min_clocks->stutter_efficiency.low_power_efficiency = 1;
+ min_clocks->stutter_efficiency.z8_stutter_efficiency = 1;
+ min_clocks->stutter_efficiency.z8_stutter_period = 100000;
+ min_clocks->zstate_support = DCN_ZSTATE_SUPPORT_ALLOW;
+}
+
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.h
index 9880d3e0398e..f51d3d8a52c3 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_translation_helper.h
@@ -25,4 +25,5 @@ void dml21_map_hw_resources(struct dml2_context *dml_ctx);
void dml21_get_pipe_mcache_config(struct dc_state *context, struct pipe_ctx *pipe_ctx, struct dml2_per_plane_programming *pln_prog, struct dml2_pipe_configuration_descriptor *mcache_pipe_config);
void dml21_set_dc_p_state_type(struct pipe_ctx *pipe_ctx, struct dml2_per_stream_programming *stream_programming, bool sub_vp_enabled);
unsigned int map_plane_to_dml21_display_cfg(const struct dml2_context *dml_ctx, unsigned int stream_id, const struct dc_plane_state *plane, const struct dc_state *context);
+void dml21_init_min_clocks_for_dc_state(struct dml2_context *in_ctx, struct dc_state *context);
#endif
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 f667026cb43e..4724b08c77e1 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
@@ -374,128 +374,142 @@ 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);
}
-void dml21_build_fams2_programming(const struct dc *dc,
+
+static unsigned int dml21_build_fams2_stream_programming_v2(const struct dc *dc,
struct dc_state *context,
struct dml2_context *dml_ctx)
{
- int i, j, k;
+ int dc_stream_idx, dc_plane_idx, dc_pipe_idx;
unsigned int num_fams2_streams = 0;
- /* reset fams2 data */
- memset(&context->bw_ctx.bw.dcn.fams2_stream_base_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES);
- memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES);
- memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2, 0, sizeof(union dmub_fams2_stream_static_sub_state_v2) * DML2_MAX_PLANES);
- memset(&context->bw_ctx.bw.dcn.fams2_global_config, 0, sizeof(struct dmub_cmd_fams2_global_config));
+ for (dc_stream_idx = 0; dc_stream_idx < context->stream_count; dc_stream_idx++) {
+ int dml_stream_idx;
+ struct dc_stream_state *phantom_stream;
+ struct dc_stream_status *phantom_status;
+ enum fams2_stream_type type = 0;
- if ((dml_ctx->v21.mode_programming.programming->fams2_required) ||
- (dml_ctx->v21.mode_programming.programming->legacy_pstate_info_for_dmu)) {
- for (i = 0; i < context->stream_count; i++) {
- int dml_stream_idx;
- struct dc_stream_state *phantom_stream;
- struct dc_stream_status *phantom_status;
- 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];
+ union dmub_cmd_fams2_config *static_sub_state = &context->bw_ctx.bw.dcn.fams2_stream_sub_params[num_fams2_streams];
- union dmub_cmd_fams2_config *static_base_state = &context->bw_ctx.bw.dcn.fams2_stream_base_params[num_fams2_streams];
- union dmub_cmd_fams2_config *static_sub_state = &context->bw_ctx.bw.dcn.fams2_stream_sub_params[num_fams2_streams];
+ struct dc_stream_state *stream = context->streams[dc_stream_idx];
- struct dc_stream_state *stream = context->streams[i];
+ 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;
+ }
- if (context->stream_status[i].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;
+ }
- 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(static_sub_state,
+ &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params,
+ sizeof(union dmub_cmd_fams2_config));
+
+ switch (dc->debug.fams_version.minor) {
+ case 1:
+ default:
+ 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);
+ }
+ }
}
+ }
- /* 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));
-
- if (dc->debug.fams_version.major == 3) {
- 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));
- } else {
- memcpy(static_sub_state,
- &dml_ctx->v21.mode_programming.programming->stream_programming[dml_stream_idx].fams2_sub_params,
- sizeof(union dmub_cmd_fams2_config));
- }
+
+ /* 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_SUBVP:
+ phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream);
+ if (!phantom_stream)
+ break;
+
+ phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream);
+
+ /* phantom status should always be present */
+ ASSERT(phantom_status);
+ if (!phantom_status)
+ break;
switch (dc->debug.fams_version.minor) {
case 1:
default:
- type = static_base_state->stream_v1.base.type;
-
- /* get information from context */
- static_base_state->stream_v1.base.num_planes = context->stream_status[i].plane_count;
- static_base_state->stream_v1.base.otg_inst = context->stream_status[i].primary_otg_inst;
-
- /* populate pipe masks for planes */
- for (j = 0; j < context->stream_status[i].plane_count; j++) {
- for (k = 0; k < dc->res_pool->pipe_count; k++) {
- if (context->res_ctx.pipe_ctx[k].stream &&
- context->res_ctx.pipe_ctx[k].stream->stream_id == stream->stream_id &&
- context->res_ctx.pipe_ctx[k].plane_state == context->stream_status[i].plane_states[j]) {
- static_base_state->stream_v1.base.pipe_mask |= (1 << k);
- static_base_state->stream_v1.base.plane_pipe_masks[j] |= (1 << k);
+ ASSERT(phantom_status->primary_otg_inst >= 0 &&
+ phantom_status->primary_otg_inst <= 0xFF);
+ static_sub_state->stream_v1.sub_state.subvp.phantom_otg_inst = (uint8_t)phantom_status->primary_otg_inst;
+
+ /* populate pipe masks for phantom planes */
+ for (dc_plane_idx = 0; dc_plane_idx < phantom_status->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 == phantom_stream->stream_id &&
+ context->res_ctx.pipe_ctx[dc_pipe_idx].plane_state == phantom_status->plane_states[dc_plane_idx]) {
+ switch (dc->debug.fams_version.minor) {
+ case 1:
+ default:
+ static_sub_state->stream_v1.sub_state.subvp.phantom_pipe_mask |= (1 << dc_pipe_idx);
+ static_sub_state->stream_v1.sub_state.subvp.phantom_plane_pipe_masks[dc_plane_idx] |= (1 << dc_pipe_idx);
+ }
}
}
}
}
+ break;
+ default:
+ ASSERT(false);
+ break;
+ }
+ num_fams2_streams++;
+ }
- /* 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_SUBVP:
- phantom_stream = dml_ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, stream);
- if (!phantom_stream)
- break;
-
- phantom_status = dml_ctx->config.callbacks.get_stream_status(context, phantom_stream);
-
- /* phantom status should always be present */
- ASSERT(phantom_status);
- if (!phantom_status)
- break;
-
- switch (dc->debug.fams_version.minor) {
- case 1:
- default:
- static_sub_state->stream_v1.sub_state.subvp.phantom_otg_inst = phantom_status->primary_otg_inst;
-
- /* populate pipe masks for phantom planes */
- for (j = 0; j < phantom_status->plane_count; j++) {
- for (k = 0; k < dc->res_pool->pipe_count; k++) {
- if (context->res_ctx.pipe_ctx[k].stream &&
- context->res_ctx.pipe_ctx[k].stream->stream_id == phantom_stream->stream_id &&
- context->res_ctx.pipe_ctx[k].plane_state == phantom_status->plane_states[j]) {
- switch (dc->debug.fams_version.minor) {
- case 1:
- default:
- static_sub_state->stream_v1.sub_state.subvp.phantom_pipe_mask |= (1 << k);
- static_sub_state->stream_v1.sub_state.subvp.phantom_plane_pipe_masks[j] |= (1 << k);
- }
- }
- }
- }
- }
- break;
- default:
- ASSERT(false);
- break;
- }
+ return num_fams2_streams;
+}
+
+void dml21_build_fams2_programming(const struct dc *dc,
+ struct dc_state *context,
+ struct dml2_context *dml_ctx)
+{
+ unsigned int num_fams2_streams = 0;
+
+ /* reset fams2 data */
+ memset(&context->bw_ctx.bw.dcn.fams2_stream_base_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES);
+ memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params, 0, sizeof(union dmub_cmd_fams2_config) * DML2_MAX_PLANES);
+ memset(&context->bw_ctx.bw.dcn.fams2_stream_sub_params_v2, 0, sizeof(union dmub_fams2_stream_static_sub_state_v2) * DML2_MAX_PLANES);
+ memset(&context->bw_ctx.bw.dcn.fams2_global_config, 0, sizeof(struct dmub_cmd_fams2_global_config));
- num_fams2_streams++;
+ 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) {
+ num_fams2_streams = dml21_build_fams2_stream_programming_v2(dc, context, dml_ctx);
}
}
@@ -508,7 +522,8 @@ void dml21_build_fams2_programming(const struct dc *dc,
context->bw_ctx.bw.dcn.fams2_global_config.num_streams = num_fams2_streams;
}
- context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
+ context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching =
+ (context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable != 0);
}
bool dml21_is_plane1_enabled(enum dml2_source_format_class source_format)
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.h
index 4bff52eaaef8..bff945a4ab3a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_utils.h
@@ -9,6 +9,7 @@
struct dc_state;
struct dc_plane_state;
struct pipe_ctx;
+struct dc_dmub_srv;
struct dml2_context;
struct dml2_display_rq_regs;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c
index 798abb2b2e67..7398f8b69adb 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.c
@@ -9,16 +9,25 @@
#include "dml21_utils.h"
#include "dml21_translation_helper.h"
#include "dml2_dc_resource_mgmt.h"
+#include "dml2_wrapper.h"
+#include "dml2_wrapper_fpu.h"
+#include "dml21_wrapper.h"
+#include "dml21_wrapper_fpu.h"
+#include "dc_fpu.h"
+
+#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED)
+#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
+#endif // !DC_RUN_WITH_PREEMPTION_ENABLED
#define INVALID -1
static bool dml21_allocate_memory(struct dml2_context **dml_ctx)
{
- *dml_ctx = vzalloc(sizeof(struct dml2_context));
+ DC_RUN_WITH_PREEMPTION_ENABLED(*dml_ctx = vzalloc(sizeof(struct dml2_context)));
if (!(*dml_ctx))
return false;
- (*dml_ctx)->v21.dml_init.dml2_instance = vzalloc(sizeof(struct dml2_instance));
+ DC_RUN_WITH_PREEMPTION_ENABLED((*dml_ctx)->v21.dml_init.dml2_instance = vzalloc(sizeof(struct dml2_instance)));
if (!((*dml_ctx)->v21.dml_init.dml2_instance))
return false;
@@ -28,45 +37,14 @@ static bool dml21_allocate_memory(struct dml2_context **dml_ctx)
(*dml_ctx)->v21.mode_support.display_config = &(*dml_ctx)->v21.display_config;
(*dml_ctx)->v21.mode_programming.display_config = (*dml_ctx)->v21.mode_support.display_config;
- (*dml_ctx)->v21.mode_programming.programming = vzalloc(sizeof(struct dml2_display_cfg_programming));
+ DC_RUN_WITH_PREEMPTION_ENABLED((*dml_ctx)->v21.mode_programming.programming = vzalloc(sizeof(struct dml2_display_cfg_programming)));
+
if (!((*dml_ctx)->v21.mode_programming.programming))
return false;
return true;
}
-static void dml21_populate_configuration_options(const struct dc *in_dc,
- struct dml2_context *dml_ctx,
- const struct dml2_configuration_options *config)
-{
- dml_ctx->config = *config;
-
- /* UCLK P-State options */
- if (in_dc->debug.dml21_force_pstate_method) {
- dml_ctx->config.pmo.force_pstate_method_enable = true;
- for (int i = 0; i < MAX_PIPES; i++)
- dml_ctx->config.pmo.force_pstate_method_values[i] = in_dc->debug.dml21_force_pstate_method_values[i];
- } else {
- dml_ctx->config.pmo.force_pstate_method_enable = false;
- }
-}
-
-static void dml21_init(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config)
-{
-
- dml_ctx->architecture = dml2_architecture_21;
-
- dml21_populate_configuration_options(in_dc, dml_ctx, config);
-
- DC_FP_START();
-
- dml21_populate_dml_init_params(&dml_ctx->v21.dml_init, &dml_ctx->config, in_dc);
-
- dml2_initialize_instance(&dml_ctx->v21.dml_init);
-
- DC_FP_END();
-}
-
bool dml21_create(const struct dc *in_dc, struct dml2_context **dml_ctx, const struct dml2_configuration_options *config)
{
/* Allocate memory for initializing DML21 instance */
@@ -84,336 +62,6 @@ void dml21_destroy(struct dml2_context *dml2)
vfree(dml2->v21.mode_programming.programming);
}
-static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *context, struct resource_context *out_new_hw_state,
- struct dml2_context *in_ctx, unsigned int pipe_cnt)
-{
- unsigned int dml_prog_idx = 0, dc_pipe_index = 0, num_dpps_required = 0;
- struct dml2_per_plane_programming *pln_prog = NULL;
- struct dml2_per_stream_programming *stream_prog = NULL;
- struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
- struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
- int num_pipes;
- unsigned int dml_phantom_prog_idx;
-
- context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
-
- /* copy global DCHUBBUB arbiter registers */
- memcpy(&context->bw_ctx.bw.dcn.arb_regs, &in_ctx->v21.mode_programming.programming->global_regs.arb_regs, sizeof(struct dml2_display_arb_regs));
-
- /* legacy only */
- context->bw_ctx.bw.dcn.compbuf_size_kb = (int)in_ctx->v21.mode_programming.programming->global_regs.arb_regs.compbuf_size * 64;
-
- context->bw_ctx.bw.dcn.mall_ss_size_bytes = 0;
- context->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes = 0;
- context->bw_ctx.bw.dcn.mall_subvp_size_bytes = 0;
-
- /* phantom's start after main planes */
- dml_phantom_prog_idx = in_ctx->v21.mode_programming.programming->display_config.num_planes;
-
- for (dml_prog_idx = 0; dml_prog_idx < DML2_MAX_PLANES; dml_prog_idx++) {
- pln_prog = &in_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
-
- if (!pln_prog->plane_descriptor)
- continue;
-
- stream_prog = &in_ctx->v21.mode_programming.programming->stream_programming[pln_prog->plane_descriptor->stream_index];
- num_dpps_required = pln_prog->num_dpps_required;
-
- if (num_dpps_required == 0) {
- continue;
- }
- num_pipes = dml21_find_dc_pipes_for_plane(dc, context, in_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
-
- if (num_pipes <= 0)
- continue;
-
- /* program each pipe */
- for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
- dml21_program_dc_pipe(in_ctx, context, dc_main_pipes[dc_pipe_index], pln_prog, stream_prog);
-
- if (pln_prog->phantom_plane.valid && dc_phantom_pipes[dc_pipe_index]) {
- dml21_program_dc_pipe(in_ctx, context, dc_phantom_pipes[dc_pipe_index], pln_prog, stream_prog);
- }
- }
-
- /* copy per plane mcache allocation */
- memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx], &pln_prog->mcache_allocation, sizeof(struct dml2_mcache_surface_allocation));
- if (pln_prog->phantom_plane.valid) {
- memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx],
- &pln_prog->phantom_plane.mcache_allocation,
- sizeof(struct dml2_mcache_surface_allocation));
-
- dml_phantom_prog_idx++;
- }
- }
-
- /* assign global clocks */
- context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
- context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
- if (in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values > 1) {
- context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz =
- in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values] * 1000;
- } else {
- context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[0] * 1000;
- }
-
- if (in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values > 1) {
- context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz =
- in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values] * 1000;
- } else {
- context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[0] * 1000;
- }
-
- /* get global mall allocation */
- if (dc->res_pool->funcs->calculate_mall_ways_from_bytes) {
- context->bw_ctx.bw.dcn.clk.num_ways = dc->res_pool->funcs->calculate_mall_ways_from_bytes(dc, context->bw_ctx.bw.dcn.mall_subvp_size_bytes);
- } else {
- context->bw_ctx.bw.dcn.clk.num_ways = 0;
- }
-}
-
-static void dml21_prepare_mcache_params(struct dml2_context *dml_ctx, struct dc_state *context, struct dc_mcache_params *mcache_params)
-{
- int dc_plane_idx = 0;
- int dml_prog_idx, stream_idx, plane_idx;
- struct dml2_per_plane_programming *pln_prog = NULL;
-
- for (stream_idx = 0; stream_idx < context->stream_count; stream_idx++) {
- for (plane_idx = 0; plane_idx < context->stream_status[stream_idx].plane_count; plane_idx++) {
- dml_prog_idx = map_plane_to_dml21_display_cfg(dml_ctx, context->streams[stream_idx]->stream_id, context->stream_status[stream_idx].plane_states[plane_idx], context);
- if (dml_prog_idx == INVALID) {
- continue;
- }
- pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
- mcache_params[dc_plane_idx].valid = pln_prog->mcache_allocation.valid;
- mcache_params[dc_plane_idx].num_mcaches_plane0 = pln_prog->mcache_allocation.num_mcaches_plane0;
- mcache_params[dc_plane_idx].num_mcaches_plane1 = pln_prog->mcache_allocation.num_mcaches_plane1;
- mcache_params[dc_plane_idx].requires_dedicated_mall_mcache = pln_prog->mcache_allocation.requires_dedicated_mall_mcache;
- mcache_params[dc_plane_idx].last_slice_sharing.plane0_plane1 = pln_prog->mcache_allocation.last_slice_sharing.plane0_plane1;
- memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane0,
- pln_prog->mcache_allocation.mcache_x_offsets_plane0,
- sizeof(int) * (DML2_MAX_MCACHES + 1));
- memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane1,
- pln_prog->mcache_allocation.mcache_x_offsets_plane1,
- sizeof(int) * (DML2_MAX_MCACHES + 1));
- dc_plane_idx++;
- }
- }
-}
-
-static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
-{
- bool result = false;
- struct dml2_build_mode_programming_in_out *mode_programming = &dml_ctx->v21.mode_programming;
- struct dc_mcache_params mcache_params[MAX_PLANES] = {0};
-
- memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
- memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
- memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params, 0, sizeof(struct dml2_core_mode_programming_in_out));
-
- if (!context)
- return true;
-
- if (context->stream_count == 0) {
- dml21_build_fams2_programming(in_dc, context, dml_ctx);
- return true;
- }
-
- /* scrub phantom's from current dc_state */
- dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
- dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
-
- /* Populate stream, plane mappings and other fields in display config. */
- result = dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
- if (!result)
- return false;
-
- DC_FP_START();
- result = dml2_build_mode_programming(mode_programming);
- DC_FP_END();
- if (!result)
- return false;
-
- /* Check and map HW resources */
- if (result && !dml_ctx->config.skip_hw_state_mapping) {
- dml21_map_hw_resources(dml_ctx);
- dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, in_dc->current_state);
- /* if subvp phantoms are present, expand them into dc context */
- dml21_handle_phantom_streams_planes(in_dc, context, dml_ctx);
-
- if (in_dc->res_pool->funcs->program_mcache_pipe_config) {
- //Prepare mcache params for each plane based on mcache output from DML
- dml21_prepare_mcache_params(dml_ctx, context, mcache_params);
-
- //populate mcache regs to each pipe
- dml_ctx->config.callbacks.allocate_mcache(context, mcache_params);
- }
- }
-
- /* Copy DML CLK, WM and REG outputs to bandwidth context */
- if (result && !dml_ctx->config.skip_hw_state_mapping) {
- dml21_calculate_rq_and_dlg_params(in_dc, context, &context->res_ctx, dml_ctx, in_dc->res_pool->pipe_count);
- dml21_copy_clocks_to_dc_state(dml_ctx, context);
- dml21_extract_watermark_sets(in_dc, &context->bw_ctx.bw.dcn.watermarks, dml_ctx);
- dml21_build_fams2_programming(in_dc, context, dml_ctx);
- }
-
- return true;
-}
-
-static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
-{
- bool is_supported = false;
- struct dml2_initialize_instance_in_out *dml_init = &dml_ctx->v21.dml_init;
- struct dml2_check_mode_supported_in_out *mode_support = &dml_ctx->v21.mode_support;
-
- memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
- memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
- memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.check_mode_supported_locals.mode_support_params, 0, sizeof(struct dml2_core_mode_support_in_out));
-
- if (!context || context->stream_count == 0)
- return true;
-
- /* Scrub phantom's from current dc_state */
- dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
- dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
-
- mode_support->dml2_instance = dml_init->dml2_instance;
- dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
- dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming;
- DC_FP_START();
- is_supported = dml2_check_mode_supported(mode_support);
- DC_FP_END();
- if (!is_supported)
- return false;
-
- return true;
-}
-
-bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx,
- enum dc_validate_mode validate_mode)
-{
- bool out = false;
-
- /* Use dml21_check_mode_support for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */
- if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
- out = dml21_check_mode_support(in_dc, context, dml_ctx);
- else
- out = dml21_mode_check_and_programming(in_dc, context, dml_ctx);
-
- return out;
-}
-
-void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
-{
- unsigned int dml_prog_idx, dml_phantom_prog_idx, dc_pipe_index;
- int num_pipes;
- struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
- struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
-
- struct dml2_per_plane_programming *pln_prog = NULL;
- struct dml2_plane_mcache_configuration_descriptor *mcache_config = NULL;
- struct prepare_mcache_programming_locals *l = &dml_ctx->v21.scratch.prepare_mcache_locals;
-
- if (context->stream_count == 0) {
- return;
- }
-
- memset(&l->build_mcache_programming_params, 0, sizeof(struct dml2_build_mcache_programming_in_out));
- l->build_mcache_programming_params.dml2_instance = dml_ctx->v21.dml_init.dml2_instance;
-
- /* phantom's start after main planes */
- dml_phantom_prog_idx = dml_ctx->v21.mode_programming.programming->display_config.num_planes;
-
- /* Build mcache programming parameters per plane per pipe */
- for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
- pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
-
- mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_prog_idx];
- memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
- mcache_config->plane_descriptor = pln_prog->plane_descriptor;
- mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx];
- mcache_config->num_pipes = pln_prog->num_dpps_required;
- l->build_mcache_programming_params.num_configurations++;
-
- if (pln_prog->num_dpps_required == 0) {
- continue;
- }
-
- num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
- if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
- dc_main_pipes[0]->plane_state == NULL)
- continue;
-
- /* get config for each pipe */
- for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
- ASSERT(dc_main_pipes[dc_pipe_index]);
- dml21_get_pipe_mcache_config(context, dc_main_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
- }
-
- /* get config for each phantom pipe */
- if (pln_prog->phantom_plane.valid &&
- dc_phantom_pipes[0] &&
- dc_main_pipes[0]->stream &&
- dc_phantom_pipes[0]->plane_state) {
- mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_phantom_prog_idx];
- memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
- mcache_config->plane_descriptor = pln_prog->plane_descriptor;
- mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx];
- mcache_config->num_pipes = pln_prog->num_dpps_required;
- l->build_mcache_programming_params.num_configurations++;
-
- for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
- ASSERT(dc_phantom_pipes[dc_pipe_index]);
- dml21_get_pipe_mcache_config(context, dc_phantom_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
- }
-
- /* increment phantom index */
- dml_phantom_prog_idx++;
- }
- }
-
- /* Call to generate mcache programming per plane per pipe for the given display configuration */
- dml2_build_mcache_programming(&l->build_mcache_programming_params);
-
- /* get per plane per pipe mcache programming */
- for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
- pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
-
- num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
- if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
- dc_main_pipes[0]->plane_state == NULL)
- continue;
-
- /* get config for each pipe */
- for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
- ASSERT(dc_main_pipes[dc_pipe_index]);
- if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index]) {
- memcpy(&dc_main_pipes[dc_pipe_index]->mcache_regs,
- l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index],
- sizeof(struct dml2_hubp_pipe_mcache_regs));
- }
- }
-
- /* get config for each phantom pipe */
- if (pln_prog->phantom_plane.valid &&
- dc_phantom_pipes[0] &&
- dc_main_pipes[0]->stream &&
- dc_phantom_pipes[0]->plane_state) {
- for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
- ASSERT(dc_phantom_pipes[dc_pipe_index]);
- if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index]) {
- memcpy(&dc_phantom_pipes[dc_pipe_index]->mcache_regs,
- l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index],
- sizeof(struct dml2_hubp_pipe_mcache_regs));
- }
- }
- /* increment phantom index */
- dml_phantom_prog_idx++;
- }
- }
-}
-
void dml21_copy(struct dml2_context *dst_dml_ctx,
struct dml2_context *src_dml_ctx)
{
@@ -439,12 +87,8 @@ void dml21_copy(struct dml2_context *dst_dml_ctx,
dst_dml_ctx->v21.mode_programming.programming = dst_dml2_programming;
- DC_FP_START();
-
/* need to initialize copied instance for internal references to be correct */
dml2_initialize_instance(&dst_dml_ctx->v21.dml_init);
-
- DC_FP_END();
}
bool dml21_create_copy(struct dml2_context **dst_dml_ctx,
@@ -459,8 +103,3 @@ bool dml21_create_copy(struct dml2_context **dst_dml_ctx,
return true;
}
-void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config)
-{
- dml21_init(in_dc, dml_ctx, config);
-}
-
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h
index b508bbcc0e16..c4813c51251b 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper.h
@@ -34,36 +34,6 @@ void dml21_copy(struct dml2_context *dst_dml_ctx,
struct dml2_context *src_dml_ctx);
bool dml21_create_copy(struct dml2_context **dst_dml_ctx,
struct dml2_context *src_dml_ctx);
-void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config);
-
-/**
- * dml21_validate - Determines if a display configuration is supported or not.
- * @in_dc: dc.
- * @context: dc_state to be validated.
- * @dml_ctx: dml21 context.
- * @validate_mode: DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX
- * will not populate context.res_ctx.
- *
- * Based on fast_validate option internally would call:
- *
- * -dml21_mode_check_and_programming - for DC_VALIDATE_MODE_AND_PROGRAMMING option
- * Calculates if dc_state can be supported on the input display
- * configuration. If supported, generates the necessary HW
- * programming for the new dc_state.
- *
- * -dml21_check_mode_support - for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX option
- * Calculates if dc_state can be supported for the input display
- * config.
- *
- * Context: Two threads may not invoke this function concurrently unless they reference
- * separate dc_states for validation.
- * Return: True if mode is supported, false otherwise.
- */
-bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx,
- enum dc_validate_mode validate_mode);
-
-/* Prepare hubp mcache_regs for hubp mcache ID and split coordinate programming */
-void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx);
/* Structure for inputting external SOCBB and DCNIP values for tool based debugging. */
struct socbb_ip_params_external {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c
new file mode 100644
index 000000000000..cc992af6ac9c
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.c
@@ -0,0 +1,381 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dml2_internal_types.h"
+#include "dml_top.h"
+#include "dml2_core_dcn4_calcs.h"
+#include "dml2_internal_shared_types.h"
+#include "dml21_utils.h"
+#include "dml21_translation_helper.h"
+#include "dml2_dc_resource_mgmt.h"
+#include "dml2_wrapper.h"
+#include "dml2_wrapper_fpu.h"
+#include "dml21_wrapper.h"
+#include "dml21_wrapper_fpu.h"
+
+#define INVALID -1
+
+static void dml21_populate_configuration_options(const struct dc *in_dc,
+ struct dml2_context *dml_ctx,
+ const struct dml2_configuration_options *config)
+{
+ dml_ctx->config = *config;
+
+ /* UCLK P-State options */
+ if (in_dc->debug.dml21_force_pstate_method) {
+ dml_ctx->config.pmo.force_pstate_method_enable = true;
+ for (int i = 0; i < MAX_PIPES; i++)
+ dml_ctx->config.pmo.force_pstate_method_values[i] = in_dc->debug.dml21_force_pstate_method_values[i];
+ } else {
+ dml_ctx->config.pmo.force_pstate_method_enable = false;
+ }
+}
+
+void dml21_init(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config)
+{
+ dml_ctx->architecture = dml2_architecture_21;
+
+ dml21_populate_configuration_options(in_dc, dml_ctx, config);
+
+ dml21_populate_dml_init_params(&dml_ctx->v21.dml_init, &dml_ctx->config, in_dc);
+
+ dml2_initialize_instance(&dml_ctx->v21.dml_init);
+}
+
+void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config)
+{
+ dml21_init(in_dc, dml_ctx, config);
+}
+
+static void dml21_calculate_rq_and_dlg_params(const struct dc *dc, struct dc_state *context, struct resource_context *out_new_hw_state,
+ struct dml2_context *in_ctx, unsigned int pipe_cnt)
+{
+ unsigned int dml_prog_idx = 0, dc_pipe_index = 0, num_dpps_required = 0;
+ struct dml2_per_plane_programming *pln_prog = NULL;
+ struct dml2_per_stream_programming *stream_prog = NULL;
+ struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
+ struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
+ int num_pipes;
+ unsigned int dml_phantom_prog_idx;
+
+ context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
+
+ /* copy global DCHUBBUB arbiter registers */
+ memcpy(&context->bw_ctx.bw.dcn.arb_regs, &in_ctx->v21.mode_programming.programming->global_regs.arb_regs, sizeof(struct dml2_display_arb_regs));
+
+ /* legacy only */
+ context->bw_ctx.bw.dcn.compbuf_size_kb = (int)in_ctx->v21.mode_programming.programming->global_regs.arb_regs.compbuf_size * 64;
+
+ context->bw_ctx.bw.dcn.mall_ss_size_bytes = 0;
+ context->bw_ctx.bw.dcn.mall_ss_psr_active_size_bytes = 0;
+ context->bw_ctx.bw.dcn.mall_subvp_size_bytes = 0;
+
+ /* phantom's start after main planes */
+ dml_phantom_prog_idx = in_ctx->v21.mode_programming.programming->display_config.num_planes;
+
+ for (dml_prog_idx = 0; dml_prog_idx < DML2_MAX_PLANES; dml_prog_idx++) {
+ pln_prog = &in_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
+
+ if (!pln_prog->plane_descriptor)
+ continue;
+
+ stream_prog = &in_ctx->v21.mode_programming.programming->stream_programming[pln_prog->plane_descriptor->stream_index];
+ num_dpps_required = pln_prog->num_dpps_required;
+
+ if (num_dpps_required == 0) {
+ continue;
+ }
+ num_pipes = dml21_find_dc_pipes_for_plane(dc, context, in_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
+
+ if (num_pipes <= 0)
+ continue;
+
+ /* program each pipe */
+ for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
+ dml21_program_dc_pipe(in_ctx, context, dc_main_pipes[dc_pipe_index], pln_prog, stream_prog);
+
+ if (pln_prog->phantom_plane.valid && dc_phantom_pipes[dc_pipe_index]) {
+ dml21_program_dc_pipe(in_ctx, context, dc_phantom_pipes[dc_pipe_index], pln_prog, stream_prog);
+ }
+ }
+
+ /* copy per plane mcache allocation */
+ memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx], &pln_prog->mcache_allocation, sizeof(struct dml2_mcache_surface_allocation));
+ if (pln_prog->phantom_plane.valid) {
+ memcpy(&context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx],
+ &pln_prog->phantom_plane.mcache_allocation,
+ sizeof(struct dml2_mcache_surface_allocation));
+
+ dml_phantom_prog_idx++;
+ }
+ }
+
+ /* assign global clocks */
+ context->bw_ctx.bw.dcn.clk.bw_dppclk_khz = context->bw_ctx.bw.dcn.clk.dppclk_khz;
+ context->bw_ctx.bw.dcn.clk.bw_dispclk_khz = context->bw_ctx.bw.dcn.clk.dispclk_khz;
+ if (in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values > 1) {
+ context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz =
+ in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.num_clk_values] * 1000;
+ } else {
+ context->bw_ctx.bw.dcn.clk.max_supported_dispclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dispclk.clk_values_khz[0] * 1000;
+ }
+
+ if (in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values > 1) {
+ context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz =
+ in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.num_clk_values] * 1000;
+ } else {
+ context->bw_ctx.bw.dcn.clk.max_supported_dppclk_khz = in_ctx->v21.dml_init.soc_bb.clk_table.dppclk.clk_values_khz[0] * 1000;
+ }
+
+ /* get global mall allocation */
+ if (dc->res_pool->funcs->calculate_mall_ways_from_bytes) {
+ context->bw_ctx.bw.dcn.clk.num_ways = dc->res_pool->funcs->calculate_mall_ways_from_bytes(dc, context->bw_ctx.bw.dcn.mall_subvp_size_bytes);
+ } else {
+ context->bw_ctx.bw.dcn.clk.num_ways = 0;
+ }
+}
+
+static void dml21_prepare_mcache_params(struct dml2_context *dml_ctx, struct dc_state *context, struct dc_mcache_params *mcache_params)
+{
+ int dc_plane_idx = 0;
+ int dml_prog_idx, stream_idx, plane_idx;
+ struct dml2_per_plane_programming *pln_prog = NULL;
+
+ for (stream_idx = 0; stream_idx < context->stream_count; stream_idx++) {
+ for (plane_idx = 0; plane_idx < context->stream_status[stream_idx].plane_count; plane_idx++) {
+ dml_prog_idx = map_plane_to_dml21_display_cfg(dml_ctx, context->streams[stream_idx]->stream_id, context->stream_status[stream_idx].plane_states[plane_idx], context);
+ if (dml_prog_idx == INVALID) {
+ continue;
+ }
+ pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
+ mcache_params[dc_plane_idx].valid = pln_prog->mcache_allocation.valid;
+ mcache_params[dc_plane_idx].num_mcaches_plane0 = pln_prog->mcache_allocation.num_mcaches_plane0;
+ mcache_params[dc_plane_idx].num_mcaches_plane1 = pln_prog->mcache_allocation.num_mcaches_plane1;
+ mcache_params[dc_plane_idx].requires_dedicated_mall_mcache = pln_prog->mcache_allocation.requires_dedicated_mall_mcache;
+ mcache_params[dc_plane_idx].last_slice_sharing.plane0_plane1 = pln_prog->mcache_allocation.last_slice_sharing.plane0_plane1;
+ memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane0,
+ pln_prog->mcache_allocation.mcache_x_offsets_plane0,
+ sizeof(int) * (DML2_MAX_MCACHES + 1));
+ memcpy(mcache_params[dc_plane_idx].mcache_x_offsets_plane1,
+ pln_prog->mcache_allocation.mcache_x_offsets_plane1,
+ sizeof(int) * (DML2_MAX_MCACHES + 1));
+ dc_plane_idx++;
+ }
+ }
+}
+
+static bool dml21_check_mode_support(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
+{
+ bool is_supported = false;
+ struct dml2_initialize_instance_in_out *dml_init = &dml_ctx->v21.dml_init;
+ struct dml2_check_mode_supported_in_out *mode_support = &dml_ctx->v21.mode_support;
+
+ memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
+ memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
+ memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.check_mode_supported_locals.mode_support_params, 0, sizeof(struct dml2_core_mode_support_in_out));
+
+ if (!context || context->stream_count == 0)
+ return true;
+
+ /* Scrub phantom's from current dc_state */
+ dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
+ dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
+
+ mode_support->dml2_instance = dml_init->dml2_instance;
+ dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
+ dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params.programming = dml_ctx->v21.mode_programming.programming;
+
+ is_supported = dml2_check_mode_supported(mode_support);
+
+ if (!is_supported)
+ return false;
+
+ return true;
+}
+
+static bool dml21_mode_check_and_programming(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
+{
+ bool result = false;
+ struct dml2_build_mode_programming_in_out *mode_programming = &dml_ctx->v21.mode_programming;
+ struct dc_mcache_params mcache_params[MAX_PLANES] = {0};
+
+ memset(&dml_ctx->v21.display_config, 0, sizeof(struct dml2_display_cfg));
+ memset(&dml_ctx->v21.dml_to_dc_pipe_mapping, 0, sizeof(struct dml2_dml_to_dc_pipe_mapping));
+ memset(&dml_ctx->v21.mode_programming.dml2_instance->scratch.build_mode_programming_locals.mode_programming_params, 0, sizeof(struct dml2_core_mode_programming_in_out));
+
+ if (!context)
+ return true;
+
+ if (context->stream_count == 0) {
+ dml21_init_min_clocks_for_dc_state(dml_ctx, context);
+ dml21_build_fams2_programming(in_dc, context, dml_ctx);
+ return true;
+ }
+
+ /* scrub phantom's from current dc_state */
+ dml_ctx->config.svp_pstate.callbacks.remove_phantom_streams_and_planes(in_dc, context);
+ dml_ctx->config.svp_pstate.callbacks.release_phantom_streams_and_planes(in_dc, context);
+
+ /* Populate stream, plane mappings and other fields in display config. */
+ result = dml21_map_dc_state_into_dml_display_cfg(in_dc, context, dml_ctx);
+ if (!result)
+ return false;
+
+ result = dml2_build_mode_programming(mode_programming);
+
+ if (!result)
+ return false;
+
+ /* Check and map HW resources */
+ if (result && !dml_ctx->config.skip_hw_state_mapping) {
+ dml21_map_hw_resources(dml_ctx);
+ dml2_map_dc_pipes(dml_ctx, context, NULL, &dml_ctx->v21.dml_to_dc_pipe_mapping, in_dc->current_state);
+ /* if subvp phantoms are present, expand them into dc context */
+ dml21_handle_phantom_streams_planes(in_dc, context, dml_ctx);
+
+ if (in_dc->res_pool->funcs->program_mcache_pipe_config) {
+ //Prepare mcache params for each plane based on mcache output from DML
+ dml21_prepare_mcache_params(dml_ctx, context, mcache_params);
+
+ //populate mcache regs to each pipe
+ dml_ctx->config.callbacks.allocate_mcache(context, mcache_params);
+ }
+ }
+
+ /* Copy DML CLK, WM and REG outputs to bandwidth context */
+ if (result && !dml_ctx->config.skip_hw_state_mapping) {
+ dml21_calculate_rq_and_dlg_params(in_dc, context, &context->res_ctx, dml_ctx, in_dc->res_pool->pipe_count);
+ dml21_copy_clocks_to_dc_state(dml_ctx, context);
+ dml21_extract_watermark_sets(in_dc, &context->bw_ctx.bw.dcn.watermarks, dml_ctx);
+ dml21_build_fams2_programming(in_dc, context, dml_ctx);
+ }
+
+ return true;
+}
+
+bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx,
+ enum dc_validate_mode validate_mode)
+{
+ bool out = false;
+
+ /* Use dml21_check_mode_support for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */
+ if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
+ out = dml21_check_mode_support(in_dc, context, dml_ctx);
+ else
+ out = dml21_mode_check_and_programming(in_dc, context, dml_ctx);
+
+ return out;
+}
+
+void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx)
+{
+ unsigned int dml_prog_idx, dml_phantom_prog_idx, dc_pipe_index;
+ int num_pipes;
+ struct pipe_ctx *dc_main_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__];
+ struct pipe_ctx *dc_phantom_pipes[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0};
+
+ struct dml2_per_plane_programming *pln_prog = NULL;
+ struct dml2_plane_mcache_configuration_descriptor *mcache_config = NULL;
+ struct prepare_mcache_programming_locals *l = &dml_ctx->v21.scratch.prepare_mcache_locals;
+
+ if (context->stream_count == 0) {
+ return;
+ }
+
+ memset(&l->build_mcache_programming_params, 0, sizeof(struct dml2_build_mcache_programming_in_out));
+ l->build_mcache_programming_params.dml2_instance = dml_ctx->v21.dml_init.dml2_instance;
+
+ /* phantom's start after main planes */
+ dml_phantom_prog_idx = dml_ctx->v21.mode_programming.programming->display_config.num_planes;
+
+ /* Build mcache programming parameters per plane per pipe */
+ for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
+ pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
+
+ mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_prog_idx];
+ memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
+ mcache_config->plane_descriptor = pln_prog->plane_descriptor;
+ mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_prog_idx];
+ ASSERT(pln_prog->num_dpps_required <= 0x7F);
+ mcache_config->num_pipes = (char)pln_prog->num_dpps_required;
+ l->build_mcache_programming_params.num_configurations++;
+
+ if (pln_prog->num_dpps_required == 0) {
+ continue;
+ }
+
+ num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
+ if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
+ dc_main_pipes[0]->plane_state == NULL)
+ continue;
+
+ /* get config for each pipe */
+ for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
+ ASSERT(dc_main_pipes[dc_pipe_index]);
+ dml21_get_pipe_mcache_config(context, dc_main_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
+ }
+
+ /* get config for each phantom pipe */
+ if (pln_prog->phantom_plane.valid &&
+ dc_phantom_pipes[0] &&
+ dc_main_pipes[0]->stream &&
+ dc_phantom_pipes[0]->plane_state) {
+ mcache_config = &l->build_mcache_programming_params.mcache_configurations[dml_phantom_prog_idx];
+ memset(mcache_config, 0, sizeof(struct dml2_plane_mcache_configuration_descriptor));
+ mcache_config->plane_descriptor = pln_prog->plane_descriptor;
+ mcache_config->mcache_allocation = &context->bw_ctx.bw.dcn.mcache_allocations[dml_phantom_prog_idx];
+ ASSERT(pln_prog->num_dpps_required <= 0x7F);
+ mcache_config->num_pipes = (char)pln_prog->num_dpps_required;
+ l->build_mcache_programming_params.num_configurations++;
+
+ for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
+ ASSERT(dc_phantom_pipes[dc_pipe_index]);
+ dml21_get_pipe_mcache_config(context, dc_phantom_pipes[dc_pipe_index], pln_prog, &mcache_config->pipe_configurations[dc_pipe_index]);
+ }
+
+ /* increment phantom index */
+ dml_phantom_prog_idx++;
+ }
+ }
+
+ /* Call to generate mcache programming per plane per pipe for the given display configuration */
+ dml2_build_mcache_programming(&l->build_mcache_programming_params);
+
+ /* get per plane per pipe mcache programming */
+ for (dml_prog_idx = 0; dml_prog_idx < dml_ctx->v21.mode_programming.programming->display_config.num_planes; dml_prog_idx++) {
+ pln_prog = &dml_ctx->v21.mode_programming.programming->plane_programming[dml_prog_idx];
+
+ num_pipes = dml21_find_dc_pipes_for_plane(in_dc, context, dml_ctx, dc_main_pipes, dc_phantom_pipes, dml_prog_idx);
+ if (num_pipes <= 0 || dc_main_pipes[0]->stream == NULL ||
+ dc_main_pipes[0]->plane_state == NULL)
+ continue;
+
+ /* get config for each pipe */
+ for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
+ ASSERT(dc_main_pipes[dc_pipe_index]);
+ if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index]) {
+ memcpy(&dc_main_pipes[dc_pipe_index]->mcache_regs,
+ l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_prog_idx][dc_pipe_index],
+ sizeof(struct dml2_hubp_pipe_mcache_regs));
+ }
+ }
+
+ /* get config for each phantom pipe */
+ if (pln_prog->phantom_plane.valid &&
+ dc_phantom_pipes[0] &&
+ dc_main_pipes[0]->stream &&
+ dc_phantom_pipes[0]->plane_state) {
+ for (dc_pipe_index = 0; dc_pipe_index < num_pipes; dc_pipe_index++) {
+ ASSERT(dc_phantom_pipes[dc_pipe_index]);
+ if (l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index]) {
+ memcpy(&dc_phantom_pipes[dc_pipe_index]->mcache_regs,
+ l->build_mcache_programming_params.per_plane_pipe_mcache_regs[dml_phantom_prog_idx][dc_pipe_index],
+ sizeof(struct dml2_hubp_pipe_mcache_regs));
+ }
+ }
+ /* increment phantom index */
+ dml_phantom_prog_idx++;
+ }
+ }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.h
new file mode 100644
index 000000000000..e5d9a456645f
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/dml21_wrapper_fpu.h
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#ifndef _DML21_WRAPPER_FPU_H_
+#define _DML21_WRAPPER_FPU_H_
+
+#include "os_types.h"
+#include "dml_top_soc_parameter_types.h"
+#include "dml_top_display_cfg_types.h"
+
+struct dc;
+struct dc_state;
+struct dml2_configuration_options;
+struct dml2_context;
+enum dc_validate_mode;
+
+/**
+ * dml21_init - Initialize DML21 context
+ * @in_dc: dc.
+ * @dml_ctx: DML21 context to initialize.
+ * @config: dml21 configuration options.
+ *
+ * Performs FPU-requiring initialization. Must be called with FPU protection.
+ */
+void dml21_init(const struct dc *in_dc, struct dml2_context *dml_ctx, const struct dml2_configuration_options *config);
+
+/**
+ * dml21_validate - Determines if a display configuration is supported or not.
+ * @in_dc: dc.
+ * @context: dc_state to be validated.
+ * @dml_ctx: dml21 context.
+ * @validate_mode: DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX
+ * will not populate context.res_ctx.
+ *
+ * Based on fast_validate option internally would call:
+ *
+ * -dml21_mode_check_and_programming - for DC_VALIDATE_MODE_AND_PROGRAMMING option
+ * Calculates if dc_state can be supported on the input display
+ * configuration. If supported, generates the necessary HW
+ * programming for the new dc_state.
+ *
+ * -dml21_check_mode_support - for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX option
+ * Calculates if dc_state can be supported for the input display
+ * config.
+ *
+ * Context: Two threads may not invoke this function concurrently unless they reference
+ * separate dc_states for validation.
+ * Return: True if mode is supported, false otherwise.
+ */
+
+void dml21_reinit(const struct dc *in_dc, struct dml2_context *dml_ctx,
+ const struct dml2_configuration_options *config);
+bool dml21_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx,
+ enum dc_validate_mode validate_mode);
+
+/* Prepare hubp mcache_regs for hubp mcache ID and split coordinate programming */
+void dml21_prepare_mcache_programming(struct dc *in_dc, struct dc_state *context, struct dml2_context *dml_ctx);
+
+#endif /* _DML21_WRAPPER_FPU_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42_soc_bb.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42_soc_bb.h
new file mode 100644
index 000000000000..c75778ea7a2c
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/inc/bounding_boxes/dcn42_soc_bb.h
@@ -0,0 +1,263 @@
+/* SPDX-License-Identifier: MIT */
+//
+// Copyright 2024 Advanced Micro Devices, Inc.
+
+#ifndef __DML_DML_DCN42_SOC_BB__
+#define __DML_DML_DCN42_SOC_BB__
+
+#include "dml_top_soc_parameter_types.h"
+
+static const struct dml2_soc_qos_parameters dml_dcn42_variant_a_soc_qos_params = {
+ .derate_table = {
+ .system_active_urgent = {
+ .dram_derate_percent_pixel = 65,
+ .dram_derate_percent_vm = 30,
+ .dram_derate_percent_pixel_and_vm = 60,
+ .fclk_derate_percent = 80,
+ .dcfclk_derate_percent = 80,
+ },
+ .system_active_average = {
+ .dram_derate_percent_pixel = 30,
+ .dram_derate_percent_vm = 30,
+ .dram_derate_percent_pixel_and_vm = 30,
+ .fclk_derate_percent = 60,
+ .dcfclk_derate_percent = 60,
+ },
+ .dcn_mall_prefetch_urgent = {
+ .dram_derate_percent_pixel = 65,
+ .dram_derate_percent_vm = 30,
+ .dram_derate_percent_pixel_and_vm = 60,
+ .fclk_derate_percent = 80,
+ .dcfclk_derate_percent = 80,
+ },
+ .dcn_mall_prefetch_average = {
+ .dram_derate_percent_pixel = 30,
+ .dram_derate_percent_vm = 30,
+ .dram_derate_percent_pixel_and_vm = 30,
+ .fclk_derate_percent = 60,
+ .dcfclk_derate_percent = 60,
+ },
+ .system_idle_average = {
+ .dram_derate_percent_pixel = 30,
+ .dram_derate_percent_vm = 30,
+ .dram_derate_percent_pixel_and_vm = 30,
+ .fclk_derate_percent = 60,
+ .dcfclk_derate_percent = 60,
+ },
+ },
+ .writeback = {
+ .base_latency_us = 12,
+ .scaling_factor_us = 0,
+ .scaling_factor_mhz = 0,
+ },
+ .qos_params = {
+ .dcn32x = {
+ .loaded_round_trip_latency_fclk_cycles = 106,
+ .urgent_latency_us = {
+ .base_latency_us = 4,
+ .base_latency_pixel_vm_us = 4,
+ .base_latency_vm_us = 4,
+ .scaling_factor_fclk_us = 0,
+ .scaling_factor_mhz = 0,
+ },
+ .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
+ .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
+ .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
+ },
+ },
+ .qos_type = dml2_qos_param_type_dcn3,
+};
+
+static const struct dml2_soc_bb dml2_socbb_dcn42 = {
+ .clk_table = {
+ .wck_ratio = {
+ .clk_values_khz = {2},
+ },
+ .uclk = {
+ .clk_values_khz = {400000},
+ .num_clk_values = 1,
+ },
+ .fclk = {
+ .clk_values_khz = {400000},
+ .num_clk_values = 1,
+ },
+ .dcfclk = {
+ .clk_values_khz = {200000},
+ .num_clk_values = 1,
+ },
+ .dispclk = {
+ .clk_values_khz = {1500000},
+ .num_clk_values = 1,
+ },
+ .dppclk = {
+ .clk_values_khz = {1500000},
+ .num_clk_values = 1,
+ },
+ .dtbclk = {
+ .clk_values_khz = {600000},
+ .num_clk_values = 1,
+ },
+ .phyclk = {
+ .clk_values_khz = {810000},
+ .num_clk_values = 1,
+ },
+ .socclk = {
+ .clk_values_khz = {600000},
+ .num_clk_values = 1,
+ },
+ .dscclk = {
+ .clk_values_khz = {500000},
+ .num_clk_values = 1,
+ },
+ .phyclk_d18 = {
+ .clk_values_khz = {667000},
+ .num_clk_values = 1,
+ },
+ .phyclk_d32 = {
+ .clk_values_khz = {625000},
+ .num_clk_values = 1,
+ },
+ .dram_config = {
+ .channel_width_bytes = 4,
+ .channel_count = 4,
+ .alt_clock_bw_conversion = true,
+ },
+ },
+
+ .qos_parameters = {
+ .derate_table = {
+ .system_active_urgent = {
+ .dram_derate_percent_pixel = 65,
+ .dram_derate_percent_vm = 30,
+ .dram_derate_percent_pixel_and_vm = 60,
+ .fclk_derate_percent = 80,
+ .dcfclk_derate_percent = 80,
+ },
+ .system_active_average = {
+ .dram_derate_percent_pixel = 30,
+ .dram_derate_percent_vm = 30,
+ .dram_derate_percent_pixel_and_vm = 30,
+ .fclk_derate_percent = 60,
+ .dcfclk_derate_percent = 60,
+ },
+ .dcn_mall_prefetch_urgent = {
+ .dram_derate_percent_pixel = 65,
+ .dram_derate_percent_vm = 30,
+ .dram_derate_percent_pixel_and_vm = 60,
+ .fclk_derate_percent = 80,
+ .dcfclk_derate_percent = 80,
+ },
+ .dcn_mall_prefetch_average = {
+ .dram_derate_percent_pixel = 30,
+ .dram_derate_percent_vm = 30,
+ .dram_derate_percent_pixel_and_vm = 30,
+ .fclk_derate_percent = 60,
+ .dcfclk_derate_percent = 60,
+ },
+ .system_idle_average = {
+ .dram_derate_percent_pixel = 30,
+ .dram_derate_percent_vm = 30,
+ .dram_derate_percent_pixel_and_vm = 30,
+ .fclk_derate_percent = 60,
+ .dcfclk_derate_percent = 60,
+ },
+ },
+ .writeback = {
+ .base_latency_us = 12,
+ .scaling_factor_us = 0,
+ .scaling_factor_mhz = 0,
+ },
+ .qos_params = {
+ .dcn32x = {
+ .loaded_round_trip_latency_fclk_cycles = 106,
+ .urgent_latency_us = {
+ .base_latency_us = 4,
+ .base_latency_pixel_vm_us = 4,
+ .base_latency_vm_us = 4,
+ .scaling_factor_fclk_us = 0,
+ .scaling_factor_mhz = 0,
+ },
+ .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096,
+ .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096,
+ .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096,
+ },
+ },
+ .qos_type = dml2_qos_param_type_dcn3,
+ },
+
+ .power_management_parameters = {
+ .dram_clk_change_blackout_us = 29,
+ .fclk_change_blackout_us = 0,
+ .g7_ppt_blackout_us = 0,
+ .stutter_enter_plus_exit_latency_us = 11,
+ .stutter_exit_latency_us = 9,
+ .z8_stutter_enter_plus_exit_latency_us = 300,
+ .z8_stutter_exit_latency_us = 200,
+ },
+
+ .vmin_limit = {
+ .dispclk_khz = 632 * 1000,
+ },
+
+ .dprefclk_mhz = 600,
+ .xtalclk_mhz = 24,
+ .pcie_refclk_mhz = 100,
+ .dchub_refclk_mhz = 50,
+ .mall_allocated_for_dcn_mbytes = 64,
+ .max_outstanding_reqs = 256,
+ .fabric_datapath_to_dcn_data_return_bytes = 32,
+ .return_bus_width_bytes = 64,
+ .hostvm_min_page_size_kbytes = 4,
+ .gpuvm_min_page_size_kbytes = 256,
+ .gpuvm_max_page_table_levels = 1,
+ .hostvm_max_non_cached_page_table_levels = 2,
+ .phy_downspread_percent = 0.38,
+ .dcn_downspread_percent = 0.38,
+ .dispclk_dppclk_vco_speed_mhz = 3000,
+ .do_urgent_latency_adjustment = 0,
+ .mem_word_bytes = 32,
+ .num_dcc_mcaches = 8,
+ .mcache_size_bytes = 2048,
+ .mcache_line_size_bytes = 32,
+ .max_fclk_for_uclk_dpm_khz = 2200 * 1000,
+};
+
+static const struct dml2_ip_capabilities dml2_dcn42_max_ip_caps = {
+ .pipe_count = 4,
+ .otg_count = 4,
+ .num_dsc = 4,
+ .max_num_dp2p0_streams = 4,
+ .max_num_hdmi_frl_outputs = 1,
+ .max_num_dp2p0_outputs = 4,
+ .rob_buffer_size_kbytes = 64,
+ .config_return_buffer_size_in_kbytes = 1792,
+ .config_return_buffer_segment_size_in_kbytes = 64,
+ .meta_fifo_size_in_kentries = 32,
+ .compressed_buffer_segment_size_in_kbytes = 64,
+ .cursor_buffer_size = 24,
+ .max_flip_time_us = 110,
+ .max_flip_time_lines = 50,
+ .hostvm_mode = 0,
+ .subvp_drr_scheduling_margin_us = 100,
+ .subvp_prefetch_end_to_mall_start_us = 15,
+ .subvp_fw_processing_delay = 15,
+ .max_vactive_det_fill_delay_us = 400,
+
+ .fams2 = {
+ .max_allow_delay_us = 100 * 1000,
+ .scheduling_delay_us = 550,
+ .vertical_interrupt_ack_delay_us = 40,
+ .allow_programming_delay_us = 18,
+ .min_allow_width_us = 20,
+ .subvp_df_throttle_delay_us = 100,
+ .subvp_programming_delay_us = 200,
+ .subvp_prefetch_to_mall_delay_us = 18,
+ .drr_programming_delay_us = 35,
+
+ .lock_timeout_us = 5000,
+ .recovery_timeout_us = 5000,
+ .flip_programming_delay_us = 300,
+ },
+};
+
+#endif
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 b44762e21550..4e9abe1a568d 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
@@ -27,6 +27,19 @@ enum dml2_swizzle_mode {
dml2_gfx11_sw_256kb_d_x,
dml2_gfx11_sw_256kb_r_x,
+ dml2_sw_linear_256b, // GFX10 SW_LINEAR only accepts 256 byte aligned pitch
+ dml2_gfx10_sw_64kb_r_x,
+ dml2_gfx102_sw_64kb_s,
+ dml2_gfx102_sw_64kb_s_t,
+ dml2_gfx102_sw_64kb_s_x,
+ dml2_gfx102_sw_64kb_r_x,
+
+ dml2_linear_64elements, // GFX7 LINEAR_ALIGNED accepts pitch alignment of the maximum of 64 elements or 256 bytes
+ dml2_gfx7_1d_thin,
+ dml2_gfx7_2d_thin_gen_zero,
+ dml2_gfx7_2d_thin_gen_one,
+ dml2_gfx7_2d_thin_arlene,
+ dml2_gfx7_2d_thin_anubis
};
enum dml2_source_format_class {
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 c4cce870877a..6152155d6073 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
@@ -160,6 +160,8 @@ struct dml2_soc_bb {
unsigned long return_bus_width_bytes;
unsigned long hostvm_min_page_size_kbytes;
unsigned long gpuvm_min_page_size_kbytes;
+ unsigned int hostvm_max_non_cached_page_table_levels;
+ unsigned int gpuvm_max_page_table_levels;
double phy_downspread_percent;
double dcn_downspread_percent;
double dispclk_dppclk_vco_speed_mhz;
@@ -190,6 +192,7 @@ struct dml2_ip_capabilities {
unsigned int max_flip_time_us;
unsigned int max_flip_time_lines;
unsigned int hostvm_mode;
+ bool dcn_mrq_present;
unsigned int subvp_drr_scheduling_margin_us;
unsigned int subvp_prefetch_end_to_mall_start_us;
unsigned int subvp_fw_processing_delay;
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 943fd3f040c3..98b26116cdc1 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
@@ -19,6 +19,8 @@ enum dml2_project_id {
dml2_project_dcn4x_stage1,
dml2_project_dcn4x_stage2,
dml2_project_dcn4x_stage2_auto_drr_svp,
+ dml2_project_dcn40,
+ dml2_project_dcn42,
};
enum dml2_pstate_change_support {
@@ -79,6 +81,7 @@ struct dml2_options {
struct dml2_pmo_options pmo_options;
};
+
struct dml2_initialize_instance_in_out {
struct dml2_instance *dml2_instance;
struct dml2_options options;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c
index eba948e187c1..99fc2f0666e2 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.c
@@ -78,6 +78,86 @@ struct dml2_core_ip_params core_dcn4_ip_caps_base = {
.subvp_swath_height_margin_lines = 16,
};
+struct dml2_core_ip_params core_dcn42_ip_caps_base = {
+ .vblank_nom_default_us = 668,
+ .remote_iommu_outstanding_translations = 256,
+ .rob_buffer_size_kbytes = 64,
+ .config_return_buffer_size_in_kbytes = 1792,
+ .config_return_buffer_segment_size_in_kbytes = 64,
+ .compressed_buffer_segment_size_in_kbytes = 64,
+ .dpte_buffer_size_in_pte_reqs_luma = 68,
+ .dpte_buffer_size_in_pte_reqs_chroma = 36,
+ .pixel_chunk_size_kbytes = 8,
+ .alpha_pixel_chunk_size_kbytes = 4,
+ .min_pixel_chunk_size_bytes = 1024,
+ .writeback_chunk_size_kbytes = 8,
+ .line_buffer_size_bits = 1171920,
+ .max_line_buffer_lines = 32,
+ .writeback_interface_buffer_size_kbytes = 90,
+
+ //Number of pipes after DCN Pipe harvesting
+ .max_num_dpp = 4,
+ .max_num_otg = 4,
+ .max_num_opp = 4,
+ .max_num_wb = 1,
+ .max_dchub_pscl_bw_pix_per_clk = 4,
+ .max_pscl_lb_bw_pix_per_clk = 2,
+ .max_lb_vscl_bw_pix_per_clk = 4,
+ .max_vscl_hscl_bw_pix_per_clk = 4,
+ .max_hscl_ratio = 6,
+ .max_vscl_ratio = 6,
+ .max_hscl_taps = 8,
+ .max_vscl_taps = 8,
+ .dispclk_ramp_margin_percent = 1,
+ .dppclk_delay_subtotal = 47,
+ .dppclk_delay_scl = 50,
+ .dppclk_delay_scl_lb_only = 16,
+ .dppclk_delay_cnvc_formatter = 28,
+ .dppclk_delay_cnvc_cursor = 6,
+ .cursor_buffer_size = 42,
+ .cursor_chunk_size = 2,
+ .dispclk_delay_subtotal = 125,
+ .max_inter_dcn_tile_repeaters = 8,
+ .writeback_max_hscl_ratio = 1,
+ .writeback_max_vscl_ratio = 1,
+ .writeback_min_hscl_ratio = 1,
+ .writeback_min_vscl_ratio = 1,
+ .writeback_max_hscl_taps = 1,
+ .writeback_max_vscl_taps = 1,
+ .writeback_line_buffer_buffer_size = 0,
+ .num_dsc = 4,
+ .maximum_dsc_bits_per_component = 12,
+ .maximum_pixels_per_line_per_dsc_unit = 5760,
+ .dsc422_native_support = true,
+ .dcc_supported = true,
+ .ptoi_supported = false,
+
+ .cursor_64bpp_support = true,
+ .dynamic_metadata_vm_enabled = false,
+
+ .max_num_hdmi_frl_outputs = 0,
+ .max_num_dp2p0_outputs = 2,
+ .max_num_dp2p0_streams = 4,
+ .imall_supported = 1,
+ .max_flip_time_us = 110,
+ .max_flip_time_lines = 50,
+ .words_per_channel = 16,
+
+ .subvp_fw_processing_delay_us = 15,
+ .subvp_pstate_allow_width_us = 20,
+ .subvp_swath_height_margin_lines = 16,
+
+ .dcn_mrq_present = 1,
+ .zero_size_buffer_entries = 512,
+ .compbuf_reserved_space_zs = 64,
+ .dcc_meta_buffer_size_bytes = 6272,
+ .meta_chunk_size_kbytes = 2,
+ .min_meta_chunk_size_bytes = 256,
+
+ .dchub_arb_to_ret_delay = 102,
+ .hostvm_mode = 1,
+};
+
static void patch_ip_caps_with_explicit_ip_params(struct dml2_ip_capabilities *ip_caps, const struct dml2_core_ip_params *ip_params)
{
ip_caps->pipe_count = ip_params->max_num_dpp;
@@ -107,6 +187,7 @@ static void patch_ip_params_with_ip_caps(struct dml2_core_ip_params *ip_params,
{
ip_params->max_num_dpp = ip_caps->pipe_count;
ip_params->max_num_otg = ip_caps->otg_count;
+ ip_params->max_num_opp = ip_caps->otg_count;
ip_params->num_dsc = ip_caps->num_dsc;
ip_params->max_num_dp2p0_streams = ip_caps->max_num_dp2p0_streams;
ip_params->max_num_dp2p0_outputs = ip_caps->max_num_dp2p0_outputs;
@@ -153,6 +234,37 @@ bool core_dcn4_initialize(struct dml2_core_initialize_in_out *in_out)
return true;
}
+bool core_dcn42_initialize(struct dml2_core_initialize_in_out *in_out)
+{
+ struct dml2_core_instance *core = in_out->instance;
+
+ if (!in_out->minimum_clock_table)
+ return false;
+ else
+ core->minimum_clock_table = in_out->minimum_clock_table;
+
+ if (in_out->explicit_ip_bb && in_out->explicit_ip_bb_size > 0) {
+ memcpy(&core->clean_me_up.mode_lib.ip, in_out->explicit_ip_bb, in_out->explicit_ip_bb_size);
+
+ // FIXME_STAGE2:
+ // DV still uses stage1 ip_param_st for each variant, need to patch the ip_caps with ip_param info
+ // Should move DV to use ip_caps but need move more overrides to ip_caps
+ patch_ip_caps_with_explicit_ip_params(in_out->ip_caps, in_out->explicit_ip_bb);
+ core->clean_me_up.mode_lib.ip.subvp_pstate_allow_width_us = core_dcn4_ip_caps_base.subvp_pstate_allow_width_us;
+ core->clean_me_up.mode_lib.ip.subvp_fw_processing_delay_us = core_dcn4_ip_caps_base.subvp_pstate_allow_width_us;
+ core->clean_me_up.mode_lib.ip.subvp_swath_height_margin_lines = core_dcn4_ip_caps_base.subvp_swath_height_margin_lines;
+ } else {
+ memcpy(&core->clean_me_up.mode_lib.ip, &core_dcn42_ip_caps_base, sizeof(struct dml2_core_ip_params));
+ patch_ip_params_with_ip_caps(&core->clean_me_up.mode_lib.ip, in_out->ip_caps);
+ core->clean_me_up.mode_lib.ip.imall_supported = false;
+ }
+
+ memcpy(&core->clean_me_up.mode_lib.soc, in_out->soc_bb, sizeof(struct dml2_soc_bb));
+ memcpy(&core->clean_me_up.mode_lib.ip_caps, in_out->ip_caps, sizeof(struct dml2_ip_capabilities));
+
+ return true;
+}
+
static void create_phantom_stream_from_main_stream(struct dml2_stream_parameters *phantom, const struct dml2_stream_parameters *main,
const struct dml2_implicit_svp_meta *meta)
{
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.h
index a68bb001a346..5c26d819a673 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_dcn4.h
@@ -5,6 +5,7 @@
#ifndef __DML2_CORE_DCN4_H__
#define __DML2_CORE_DCN4_H__
bool core_dcn4_initialize(struct dml2_core_initialize_in_out *in_out);
+bool core_dcn42_initialize(struct dml2_core_initialize_in_out *in_out);
bool core_dcn4_mode_support(struct dml2_core_mode_support_in_out *in_out);
bool core_dcn4_mode_programming(struct dml2_core_mode_programming_in_out *in_out);
bool core_dcn4_populate_informative(struct dml2_core_populate_informative_in_out *in_out);
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 ca5ac3c0deb5..f6402e199354 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
@@ -202,7 +202,7 @@ static unsigned int dml_round_to_multiple(unsigned int num, unsigned int multipl
return (num - remainder);
}
-static unsigned int dml_get_num_active_pipes(int unsigned num_planes, const struct core_display_cfg_support_info *cfg_support_info)
+static unsigned int dml_get_num_active_pipes(unsigned int num_planes, const struct core_display_cfg_support_info *cfg_support_info)
{
unsigned int num_active_pipes = 0;
@@ -546,9 +546,9 @@ static bool dml_is_vertical_rotation(enum dml2_rotation_angle Scan)
return is_vert;
}
-static int unsigned dml_get_gfx_version(enum dml2_swizzle_mode sw_mode)
+static unsigned int dml_get_gfx_version(enum dml2_swizzle_mode sw_mode)
{
- int unsigned version = 0;
+ unsigned int version = 0;
if (sw_mode == dml2_sw_linear ||
sw_mode == dml2_sw_256b_2d ||
@@ -1761,7 +1761,7 @@ static unsigned int CalculateVMAndRowBytes(struct dml2_core_shared_calculate_vm_
*p->PixelPTEBytesPerRow = (unsigned int)((double)*p->dpte_row_width_ub / (double)*p->PixelPTEReqWidth * *p->PTERequestSize);
// VBA_DELTA, VBA doesn't have programming value for pte row height linear.
- *p->dpte_row_height_linear = (unsigned int)1 << (unsigned int)math_floor2(math_log((float)(p->PTEBufferSizeInRequests * PixelPTEReqWidth_linear / p->Pitch), 2.0), 1);
+ *p->dpte_row_height_linear = 1U << (unsigned int)math_floor2(math_log((float)(p->PTEBufferSizeInRequests * PixelPTEReqWidth_linear / p->Pitch), 2.0), 1);
if (*p->dpte_row_height_linear > 128)
*p->dpte_row_height_linear = 128;
@@ -3377,7 +3377,7 @@ static void calculate_cursor_req_attributes(
DML_LOG_VERBOSE("DML::%s: cursor_bytes_per_line = %d\n", __func__, *cursor_bytes_per_line);
DML_LOG_VERBOSE("DML::%s: cursor_bytes_per_chunk = %d\n", __func__, *cursor_bytes_per_chunk);
DML_LOG_VERBOSE("DML::%s: cursor_bytes = %d\n", __func__, *cursor_bytes);
- DML_LOG_VERBOSE("DML::%s: cursor_pitch = %d\n", __func__, cursor_bpp == 2 ? 256 : (unsigned int)1 << (unsigned int)math_ceil2(math_log((float)cursor_width, 2), 1));
+ DML_LOG_VERBOSE("DML::%s: cursor_pitch = %d\n", __func__, cursor_bpp == 2 ? 256 : 1U << (unsigned int)math_ceil2(math_log((float)cursor_width, 2), 1));
#endif
}
@@ -12205,15 +12205,15 @@ static void rq_dlg_get_wm_regs(const struct dml2_display_cfg *display_cfg, const
{
double refclk_freq_in_mhz = (display_cfg->overrides.hw.dlg_ref_clk_mhz > 0) ? (double)display_cfg->overrides.hw.dlg_ref_clk_mhz : mode_lib->soc.dchub_refclk_mhz;
- wm_regs->fclk_pstate = (int unsigned)(mode_lib->mp.Watermark.FCLKChangeWatermark * refclk_freq_in_mhz);
- wm_regs->sr_enter = (int unsigned)(mode_lib->mp.Watermark.StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
- wm_regs->sr_exit = (int unsigned)(mode_lib->mp.Watermark.StutterExitWatermark * refclk_freq_in_mhz);
- wm_regs->sr_enter_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
- wm_regs->sr_exit_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterExitWatermark * refclk_freq_in_mhz);
- wm_regs->temp_read_or_ppt = (int unsigned)(mode_lib->mp.Watermark.temp_read_or_ppt_watermark_us * refclk_freq_in_mhz);
- wm_regs->uclk_pstate = (int unsigned)(mode_lib->mp.Watermark.DRAMClockChangeWatermark * refclk_freq_in_mhz);
- wm_regs->urgent = (int unsigned)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz);
- wm_regs->usr = (int unsigned)(mode_lib->mp.Watermark.USRRetrainingWatermark * refclk_freq_in_mhz);
+ wm_regs->fclk_pstate = (unsigned int)(mode_lib->mp.Watermark.FCLKChangeWatermark * refclk_freq_in_mhz);
+ wm_regs->sr_enter = (unsigned int)(mode_lib->mp.Watermark.StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
+ wm_regs->sr_exit = (unsigned int)(mode_lib->mp.Watermark.StutterExitWatermark * refclk_freq_in_mhz);
+ wm_regs->sr_enter_z8 = (unsigned int)(mode_lib->mp.Watermark.Z8StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
+ wm_regs->sr_exit_z8 = (unsigned int)(mode_lib->mp.Watermark.Z8StutterExitWatermark * refclk_freq_in_mhz);
+ wm_regs->temp_read_or_ppt = (unsigned int)(mode_lib->mp.Watermark.temp_read_or_ppt_watermark_us * refclk_freq_in_mhz);
+ wm_regs->uclk_pstate = (unsigned int)(mode_lib->mp.Watermark.DRAMClockChangeWatermark * refclk_freq_in_mhz);
+ wm_regs->urgent = (unsigned int)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz);
+ wm_regs->usr = (unsigned int)(mode_lib->mp.Watermark.USRRetrainingWatermark * refclk_freq_in_mhz);
wm_regs->refcyc_per_trip_to_mem = (unsigned int)(mode_lib->mp.UrgentLatency * refclk_freq_in_mhz);
wm_regs->refcyc_per_meta_trip_to_mem = (unsigned int)(mode_lib->mp.MetaTripToMemory * refclk_freq_in_mhz);
wm_regs->frac_urg_bw_flip = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidthImmediateFlip * 1000);
@@ -12262,11 +12262,15 @@ static void rq_dlg_get_rq_reg(struct dml2_display_rq_regs *rq_regs,
unsigned int pixel_chunk_bytes = 0;
unsigned int min_pixel_chunk_bytes = 0;
+ unsigned int meta_chunk_bytes = 0;
+ unsigned int min_meta_chunk_bytes = 0;
unsigned int dpte_group_bytes = 0;
unsigned int mpte_group_bytes = 0;
unsigned int p1_pixel_chunk_bytes = 0;
unsigned int p1_min_pixel_chunk_bytes = 0;
+ unsigned int p1_meta_chunk_bytes = 0;
+ unsigned int p1_min_meta_chunk_bytes = 0;
unsigned int p1_dpte_group_bytes = 0;
unsigned int p1_mpte_group_bytes = 0;
@@ -12287,8 +12291,13 @@ static void rq_dlg_get_rq_reg(struct dml2_display_rq_regs *rq_regs,
dpte_group_bytes = (unsigned int)(dml_get_dpte_group_size_in_bytes(mode_lib, pipe_idx));
mpte_group_bytes = (unsigned int)(dml_get_vm_group_size_in_bytes(mode_lib, pipe_idx));
+ meta_chunk_bytes = (unsigned int)(mode_lib->ip.meta_chunk_size_kbytes * 1024);
+ min_meta_chunk_bytes = (unsigned int)(mode_lib->ip.min_meta_chunk_size_bytes);
+
p1_pixel_chunk_bytes = pixel_chunk_bytes;
p1_min_pixel_chunk_bytes = min_pixel_chunk_bytes;
+ p1_meta_chunk_bytes = meta_chunk_bytes;
+ p1_min_meta_chunk_bytes = min_meta_chunk_bytes;
p1_dpte_group_bytes = dpte_group_bytes;
p1_mpte_group_bytes = mpte_group_bytes;
@@ -12309,6 +12318,19 @@ static void rq_dlg_get_rq_reg(struct dml2_display_rq_regs *rq_regs,
else
rq_regs->rq_regs_c.min_chunk_size = log_and_substract_if_non_zero(p1_min_pixel_chunk_bytes, 8 - 1);
+ rq_regs->rq_regs_l.meta_chunk_size = log_and_substract_if_non_zero(meta_chunk_bytes, 10);
+ rq_regs->rq_regs_c.meta_chunk_size = log_and_substract_if_non_zero(p1_meta_chunk_bytes, 10);
+
+ if (min_meta_chunk_bytes == 0)
+ rq_regs->rq_regs_l.min_meta_chunk_size = 0;
+ else
+ rq_regs->rq_regs_l.min_meta_chunk_size = log_and_substract_if_non_zero(min_meta_chunk_bytes, 6 - 1);
+
+ if (min_meta_chunk_bytes == 0)
+ rq_regs->rq_regs_c.min_meta_chunk_size = 0;
+ else
+ rq_regs->rq_regs_c.min_meta_chunk_size = log_and_substract_if_non_zero(p1_min_meta_chunk_bytes, 6 - 1);
+
rq_regs->rq_regs_l.dpte_group_size = log_and_substract_if_non_zero(dpte_group_bytes, 6);
rq_regs->rq_regs_l.mpte_group_size = log_and_substract_if_non_zero(mpte_group_bytes, 6);
rq_regs->rq_regs_c.dpte_group_size = log_and_substract_if_non_zero(p1_dpte_group_bytes, 6);
@@ -12670,7 +12692,7 @@ static void rq_dlg_get_dlg_reg(
disp_dlg_regs->refcyc_per_vm_req_flip = (unsigned int)(math_pow(2, 23) - 1);
- DML_ASSERT(disp_dlg_regs->dst_y_after_scaler < (unsigned int)8);
+ DML_ASSERT(disp_dlg_regs->dst_y_after_scaler < 8U);
DML_ASSERT(disp_dlg_regs->refcyc_x_after_scaler < (unsigned int)math_pow(2, 13));
if (disp_dlg_regs->dst_y_per_pte_row_nom_l >= (unsigned int)math_pow(2, 17)) {
@@ -13226,7 +13248,7 @@ void dml2_core_calcs_get_informative(const struct dml2_core_internal_display_mod
out->informative.misc.cstate_max_cap_mode = dml_get_cstate_max_cap_mode(mode_lib);
- out->min_clocks.dcn4x.dpprefclk_khz = (int unsigned)dml_get_global_dppclk_khz(mode_lib);
+ out->min_clocks.dcn4x.dpprefclk_khz = (unsigned int)dml_get_global_dppclk_khz(mode_lib);
out->informative.qos.max_active_fclk_change_latency_supported = dml_get_fclk_change_latency(mode_lib);
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 cc4f0663c6d6..6cad99c21139 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
@@ -21,6 +21,7 @@ bool dml2_core_create(enum dml2_project_id project_id, struct dml2_core_instance
case dml2_project_dcn4x_stage1:
result = false;
break;
+ case dml2_project_dcn40:
case dml2_project_dcn4x_stage2:
case dml2_project_dcn4x_stage2_auto_drr_svp:
out->initialize = &core_dcn4_initialize;
@@ -30,6 +31,14 @@ 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_dcn42:
+ out->initialize = &core_dcn42_initialize;
+ out->mode_support = &core_dcn4_mode_support;
+ out->mode_programming = &core_dcn4_mode_programming;
+ out->populate_informative = &core_dcn4_populate_informative;
+ out->calculate_mcache_allocation = &core_dcn4_calculate_mcache_allocation;
+ result = true;
+ break;
case dml2_project_invalid:
default:
break;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.c
index b57d0f6ea6a1..6930ba7ce5b7 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.c
@@ -428,6 +428,9 @@ bool dml2_core_utils_is_phantom_pipe(const struct dml2_plane_parameters *plane_c
unsigned int dml2_core_utils_get_tile_block_size_bytes(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel)
{
+ if (dml2_core_utils_get_gfx_version(sw_mode) == 10 || dml2_core_utils_get_gfx_version(sw_mode) == 7) {
+ return dml2_core_utils_get_tile_block_size_bytes_backcompat(sw_mode, byte_per_pixel);
+ }
if (sw_mode == dml2_sw_linear)
return 256;
@@ -459,14 +462,56 @@ unsigned int dml2_core_utils_get_tile_block_size_bytes(enum dml2_swizzle_mode sw
};
}
+unsigned int dml2_core_utils_get_tile_block_size_bytes_backcompat(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel)
+{
+ if (sw_mode == dml2_sw_linear_256b)
+ return 256;
+ else if (sw_mode == dml2_gfx10_sw_64kb_r_x)
+ return 65536;
+ else if (sw_mode == dml2_gfx102_sw_64kb_s)
+ return 65536;
+ else if (sw_mode == dml2_gfx102_sw_64kb_s_t)
+ return 65536;
+ else if (sw_mode == dml2_gfx102_sw_64kb_s_x)
+ return 65536;
+ else if (sw_mode == dml2_gfx102_sw_64kb_r_x)
+ return 65536;
+ else if (sw_mode == dml2_linear_64elements)
+ return 256;
+ else if (sw_mode == dml2_gfx7_1d_thin)
+ return 256;
+ else if (sw_mode == dml2_gfx7_2d_thin_gen_zero)
+ return (128 * 64 * byte_per_pixel);
+ else if (sw_mode == dml2_gfx7_2d_thin_gen_one)
+ return (128 * 128 * byte_per_pixel);
+ else if (sw_mode == dml2_gfx7_2d_thin_arlene)
+ return (64 * 32 * byte_per_pixel);
+ else if (sw_mode == dml2_gfx7_2d_thin_anubis)
+ return (128 * 128 * byte_per_pixel);
+ else {
+ DML_ASSERT(0);
+ return 256;
+ };
+}
+
bool dml2_core_utils_get_segment_horizontal_contiguous(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel)
{
- return (byte_per_pixel != 2);
+ if (dml2_core_utils_get_gfx_version(sw_mode) == 10 || dml2_core_utils_get_gfx_version(sw_mode) == 7) {
+ return dml2_core_utils_get_segment_horizontal_contiguous_backcompat(sw_mode, byte_per_pixel);
+ } else {
+ return (byte_per_pixel != 2);
+ }
+}
+
+bool dml2_core_utils_get_segment_horizontal_contiguous_backcompat(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel)
+{
+ return !((byte_per_pixel == 4) &&
+ ((sw_mode == dml2_gfx10_sw_64kb_r_x) || (sw_mode == dml2_gfx102_sw_64kb_s) || (sw_mode == dml2_gfx102_sw_64kb_s_t) || (sw_mode == dml2_gfx102_sw_64kb_s_x)));
}
bool dml2_core_utils_is_linear(enum dml2_swizzle_mode sw_mode)
{
- return sw_mode == dml2_sw_linear;
+ return (sw_mode == dml2_sw_linear || sw_mode == dml2_sw_linear_256b || sw_mode == dml2_linear_64elements);
};
@@ -499,6 +544,20 @@ int unsigned dml2_core_utils_get_gfx_version(enum dml2_swizzle_mode sw_mode)
sw_mode == dml2_gfx11_sw_256kb_d_x ||
sw_mode == dml2_gfx11_sw_256kb_r_x)
version = 11;
+ else if (sw_mode == dml2_sw_linear_256b ||
+ sw_mode == dml2_gfx10_sw_64kb_r_x ||
+ sw_mode == dml2_gfx102_sw_64kb_s ||
+ sw_mode == dml2_gfx102_sw_64kb_s_t ||
+ sw_mode == dml2_gfx102_sw_64kb_s_x ||
+ sw_mode == dml2_gfx102_sw_64kb_r_x)
+ version = 10;
+ else if (sw_mode == dml2_linear_64elements ||
+ sw_mode == dml2_gfx7_1d_thin ||
+ sw_mode == dml2_gfx7_2d_thin_gen_zero ||
+ sw_mode == dml2_gfx7_2d_thin_gen_one ||
+ sw_mode == dml2_gfx7_2d_thin_arlene ||
+ sw_mode == dml2_gfx7_2d_thin_anubis)
+ version = 7;
else {
DML_LOG_VERBOSE("ERROR: Invalid sw_mode setting! val=%u\n", sw_mode);
DML_ASSERT(0);
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.h
index 95f0d017add4..471e73ed671c 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_core/dml2_core_utils.h
@@ -22,6 +22,8 @@ void dml2_core_utils_pipe_plane_mapping(const struct core_display_cfg_support_in
bool dml2_core_utils_is_phantom_pipe(const struct dml2_plane_parameters *plane_cfg);
unsigned int dml2_core_utils_get_tile_block_size_bytes(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel);
bool dml2_core_utils_get_segment_horizontal_contiguous(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel);
+unsigned int dml2_core_utils_get_tile_block_size_bytes_backcompat(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel);
+bool dml2_core_utils_get_segment_horizontal_contiguous_backcompat(enum dml2_swizzle_mode sw_mode, unsigned int byte_per_pixel);
bool dml2_core_utils_is_vertical_rotation(enum dml2_rotation_angle Scan);
bool dml2_core_utils_is_linear(enum dml2_swizzle_mode sw_mode);
int unsigned dml2_core_utils_get_gfx_version(enum dml2_swizzle_mode sw_mode);
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c
index 9d7741fd0adb..ab0b4a4b5d65 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.c
@@ -279,6 +279,26 @@ static bool round_up_and_copy_to_next_dpm(unsigned long min_value, unsigned long
bool result = false;
int index = 0;
+ /* Guard against empty clock tables (e.g. DTBCLK on DCN42B where the
+ * clock is tied off and num_clk_values == 0). Without this check the
+ * else-if branch below would evaluate
+ * clk_values_khz[num_clk_values - 1] with num_clk_values == 0, which
+ * wraps the unsigned char index to 255 — a 235-element out-of-bounds
+ * read on an array of DML_MAX_CLK_TABLE_SIZE (20) entries.
+ *
+ * Semantic: if the clock doesn't exist on this ASIC but no frequency
+ * is required (min_value == 0), the request is trivially satisfied.
+ * If a non-zero frequency is required but the clock is absent, the
+ * configuration is unsupportable.
+ */
+ if (clock_table->num_clk_values == 0) {
+ if (min_value == 0) {
+ *rounded_value = 0;
+ return true;
+ }
+ return false;
+ }
+
if (clock_table->num_clk_values > 2) {
while (index < clock_table->num_clk_values && clock_table->clk_values_khz[index] < min_value)
index++;
@@ -802,3 +822,36 @@ bool dpmm_dcn4_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_
return true;
}
+bool dpmm_dcn42_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_out)
+{
+ const struct dml2_display_cfg *display_cfg = &in_out->display_cfg->display_config;
+ const struct dml2_core_internal_display_mode_lib *mode_lib = &in_out->core->clean_me_up.mode_lib;
+ struct dml2_dchub_global_register_set *dchubbub_regs = &in_out->programming->global_regs;
+
+ double refclk_freq_in_mhz = (display_cfg->overrides.hw.dlg_ref_clk_mhz > 0) ? (double)display_cfg->overrides.hw.dlg_ref_clk_mhz : mode_lib->soc.dchub_refclk_mhz;
+
+ /* set A */
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].fclk_pstate = (int unsigned)(mode_lib->mp.Watermark.FCLKChangeWatermark * refclk_freq_in_mhz);
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_enter = (int unsigned)(mode_lib->mp.Watermark.StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_exit = (int unsigned)(mode_lib->mp.Watermark.StutterExitWatermark * refclk_freq_in_mhz);
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_enter_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterEnterPlusExitWatermark * refclk_freq_in_mhz);
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].sr_exit_z8 = (int unsigned)(mode_lib->mp.Watermark.Z8StutterExitWatermark * refclk_freq_in_mhz);
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].temp_read_or_ppt = (int unsigned)(mode_lib->mp.Watermark.temp_read_or_ppt_watermark_us * refclk_freq_in_mhz);
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].uclk_pstate = (int unsigned)(mode_lib->mp.Watermark.DRAMClockChangeWatermark * refclk_freq_in_mhz);
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].urgent = (int unsigned)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz);
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].usr = (int unsigned)(mode_lib->mp.Watermark.USRRetrainingWatermark * refclk_freq_in_mhz);
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].refcyc_per_trip_to_mem = (unsigned int)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz);
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].refcyc_per_meta_trip_to_mem = (unsigned int)(mode_lib->mp.Watermark.UrgentWatermark * refclk_freq_in_mhz);
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].frac_urg_bw_flip = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidthImmediateFlip * 1000);
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].frac_urg_bw_nom = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidth * 1000);
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A].frac_urg_bw_mall = (unsigned int)(mode_lib->mp.FractionOfUrgentBandwidthMALL * 1000);
+
+ /* set B */
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_B] = dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A];
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_C] = dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A];
+ dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_D] = dchubbub_regs->wm_regs[DML2_DCHUB_WATERMARK_SET_A];
+
+ dchubbub_regs->num_watermark_sets = 4;
+
+ return true;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.h
index e7b58f2efda4..5fbd07e238a8 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.h
@@ -10,5 +10,6 @@
bool dpmm_dcn3_map_mode_to_soc_dpm(struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out);
bool dpmm_dcn4_map_mode_to_soc_dpm(struct dml2_dpmm_map_mode_to_soc_dpm_params_in_out *in_out);
bool dpmm_dcn4_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_out);
+bool dpmm_dcn42_map_watermarks(struct dml2_dpmm_map_watermarks_params_in_out *in_out);
#endif
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 dfd01440737d..1f2d9e97f5fd 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
@@ -31,6 +31,7 @@ bool dml2_dpmm_create(enum dml2_project_id project_id, struct dml2_dpmm_instance
out->map_watermarks = &dummy_map_watermarks;
result = true;
break;
+ case dml2_project_dcn40:
case dml2_project_dcn4x_stage2:
out->map_mode_to_soc_dpm = &dpmm_dcn3_map_mode_to_soc_dpm;
out->map_watermarks = &dummy_map_watermarks;
@@ -41,6 +42,11 @@ bool dml2_dpmm_create(enum dml2_project_id project_id, struct dml2_dpmm_instance
out->map_watermarks = &dpmm_dcn4_map_watermarks;
result = true;
break;
+ case dml2_project_dcn42:
+ out->map_mode_to_soc_dpm = &dpmm_dcn4_map_mode_to_soc_dpm;
+ out->map_watermarks = &dpmm_dcn42_map_watermarks;
+ result = true;
+ break;
case dml2_project_invalid:
default:
break;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c
index a265f254152c..eab13e1c96fd 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.c
@@ -178,9 +178,12 @@ static bool build_min_clock_table(const struct dml2_soc_bb *soc_bb, struct dml2_
min_table->max_clocks_khz.dispclk = soc_bb->clk_table.dispclk.clk_values_khz[soc_bb->clk_table.dispclk.num_clk_values - 1];
min_table->max_clocks_khz.dppclk = soc_bb->clk_table.dppclk.clk_values_khz[soc_bb->clk_table.dppclk.num_clk_values - 1];
- min_table->max_clocks_khz.dscclk = soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1];
- min_table->max_clocks_khz.dtbclk = soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1];
- min_table->max_clocks_khz.phyclk = soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1];
+ min_table->max_clocks_khz.dscclk = (soc_bb->clk_table.dscclk.num_clk_values > 0) ?
+ soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1] : 0;
+ min_table->max_clocks_khz.dtbclk = (soc_bb->clk_table.dtbclk.num_clk_values > 0) ?
+ soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1] : 0;
+ min_table->max_clocks_khz.phyclk = (soc_bb->clk_table.phyclk.num_clk_values > 0) ?
+ soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1] : 0;
min_table->max_ss_clocks_khz.dispclk = (unsigned int)((double)min_table->max_clocks_khz.dispclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
min_table->max_ss_clocks_khz.dppclk = (unsigned int)((double)min_table->max_clocks_khz.dppclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.h
index f54fde8fba90..02da6f45cbf7 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn4.h
@@ -10,4 +10,4 @@
bool mcg_dcn4_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out);
bool mcg_dcn4_unit_test(void);
-#endif \ No newline at end of file
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c
new file mode 100644
index 000000000000..3eaeff39ee79
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dml2_mcg_dcn42.h"
+#include "dml_top_soc_parameter_types.h"
+
+static unsigned long long uclk_to_dram_bw_kbps(unsigned long uclk_khz, const struct dml2_dram_params *dram_config, unsigned long wck_ratio)
+{
+ unsigned long long bw_kbps = 0;
+
+ bw_kbps = (unsigned long long) uclk_khz * dram_config->channel_count * dram_config->channel_width_bytes * wck_ratio * 2;
+ return bw_kbps;
+}
+
+static bool build_min_clk_table_coarse_grained(const struct dml2_soc_bb *soc_bb, struct dml2_mcg_min_clock_table *min_table)
+{
+ int i;
+
+ for (i = 0; i < soc_bb->clk_table.fclk.num_clk_values; i++) {
+ if (i < soc_bb->clk_table.uclk.num_clk_values) {
+ min_table->dram_bw_table.entries[i].pre_derate_dram_bw_kbps =
+ uclk_to_dram_bw_kbps(soc_bb->clk_table.uclk.clk_values_khz[i], &soc_bb->clk_table.dram_config, soc_bb->clk_table.wck_ratio.clk_values_khz[i]);
+ min_table->dram_bw_table.entries[i].min_uclk_khz = soc_bb->clk_table.uclk.clk_values_khz[i];
+ } else {
+ min_table->dram_bw_table.entries[i].pre_derate_dram_bw_kbps = min_table->dram_bw_table.entries[soc_bb->clk_table.uclk.num_clk_values - 1].pre_derate_dram_bw_kbps;
+ min_table->dram_bw_table.entries[i].min_uclk_khz = soc_bb->clk_table.uclk.clk_values_khz[soc_bb->clk_table.uclk.num_clk_values - 1];
+ }
+
+ min_table->dram_bw_table.entries[i].min_dcfclk_khz = soc_bb->clk_table.dcfclk.clk_values_khz[i];
+ min_table->dram_bw_table.entries[i].min_fclk_khz = soc_bb->clk_table.fclk.clk_values_khz[i];
+ }
+ min_table->dram_bw_table.num_entries = soc_bb->clk_table.fclk.num_clk_values;
+
+ return true;
+}
+
+static bool build_min_clock_table(const struct dml2_soc_bb *soc_bb, struct dml2_mcg_min_clock_table *min_table)
+{
+ bool result;
+
+ if (!soc_bb || !min_table)
+ return false;
+
+
+ if (soc_bb->clk_table.uclk.num_clk_values > DML_MCG_MAX_CLK_TABLE_SIZE)
+ return false;
+
+ min_table->fixed_clocks_khz.amclk = 0;
+ min_table->fixed_clocks_khz.dprefclk = soc_bb->dprefclk_mhz * 1000;
+ min_table->fixed_clocks_khz.pcierefclk = soc_bb->pcie_refclk_mhz * 1000;
+ min_table->fixed_clocks_khz.dchubrefclk = soc_bb->dchub_refclk_mhz * 1000;
+ min_table->fixed_clocks_khz.xtalclk = soc_bb->xtalclk_mhz * 1000;
+
+ min_table->max_clocks_khz.dispclk = soc_bb->clk_table.dispclk.clk_values_khz[soc_bb->clk_table.dispclk.num_clk_values - 1];
+ min_table->max_clocks_khz.dppclk = soc_bb->clk_table.dppclk.clk_values_khz[soc_bb->clk_table.dppclk.num_clk_values - 1];
+ min_table->max_clocks_khz.dscclk = (soc_bb->clk_table.dscclk.num_clk_values > 0) ?
+ soc_bb->clk_table.dscclk.clk_values_khz[soc_bb->clk_table.dscclk.num_clk_values - 1] : 0;
+ min_table->max_clocks_khz.dtbclk = (soc_bb->clk_table.dtbclk.num_clk_values > 0) ?
+ soc_bb->clk_table.dtbclk.clk_values_khz[soc_bb->clk_table.dtbclk.num_clk_values - 1] : 0;
+ min_table->max_clocks_khz.phyclk = (soc_bb->clk_table.phyclk.num_clk_values > 0) ?
+ soc_bb->clk_table.phyclk.clk_values_khz[soc_bb->clk_table.phyclk.num_clk_values - 1] : 0;
+
+ min_table->max_ss_clocks_khz.dispclk = (unsigned int)((double)min_table->max_clocks_khz.dispclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
+ min_table->max_ss_clocks_khz.dppclk = (unsigned int)((double)min_table->max_clocks_khz.dppclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
+ min_table->max_ss_clocks_khz.dtbclk = (unsigned int)((double)min_table->max_clocks_khz.dtbclk / (1.0 + soc_bb->dcn_downspread_percent / 100.0));
+
+ min_table->max_clocks_khz.dcfclk = soc_bb->clk_table.dcfclk.clk_values_khz[soc_bb->clk_table.dcfclk.num_clk_values - 1];
+ min_table->max_clocks_khz.fclk = soc_bb->clk_table.fclk.clk_values_khz[soc_bb->clk_table.fclk.num_clk_values - 1];
+
+ result = build_min_clk_table_coarse_grained(soc_bb, min_table);
+
+ return result;
+}
+
+bool mcg_dcn42_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out)
+{
+ return build_min_clock_table(in_out->soc_bb, in_out->min_clk_table);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.h
new file mode 100644
index 000000000000..d4ea49e3e674
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_mcg/dml2_mcg_dcn42.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: MIT */
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#ifndef __DML2_MCG_DCN42_H__
+#define __DML2_MCG_DCN42_H__
+
+#include "dml2_internal_shared_types.h"
+
+bool mcg_dcn42_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out);
+
+#endif
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 c60b8fe90819..3dcd2c250633 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
@@ -4,6 +4,7 @@
#include "dml2_mcg_factory.h"
#include "dml2_mcg_dcn4.h"
+#include "dml2_mcg_dcn42.h"
#include "dml2_external_lib_deps.h"
static bool dummy_build_min_clock_table(struct dml2_mcg_build_min_clock_table_params_in_out *in_out)
@@ -25,11 +26,16 @@ bool dml2_mcg_create(enum dml2_project_id project_id, struct dml2_mcg_instance *
out->build_min_clock_table = &dummy_build_min_clock_table;
result = true;
break;
+ case dml2_project_dcn40:
case dml2_project_dcn4x_stage2:
case dml2_project_dcn4x_stage2_auto_drr_svp:
out->build_min_clock_table = &mcg_dcn4_build_min_clock_table;
result = true;
break;
+ case dml2_project_dcn42:
+ out->build_min_clock_table = &mcg_dcn42_build_min_clock_table;
+ result = true;
+ break;
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 c26e100fcaf2..e8691983c0eb 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,7 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_1_display[] = {
.allow_state_increase = true,
},
+
// Then VBlank
{
.per_stream_pstate_method = { dml2_pstate_method_vblank, dml2_pstate_method_na, dml2_pstate_method_na, dml2_pstate_method_na },
@@ -53,6 +54,7 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_2_display[] = {
.allow_state_increase = true,
},
+
// Then VActive + VBlank
{
.per_stream_pstate_method = { dml2_pstate_method_vactive, dml2_pstate_method_vblank, dml2_pstate_method_na, dml2_pstate_method_na },
@@ -113,6 +115,7 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_3_display[] = {
.allow_state_increase = true,
},
+
// VActive + 1 VBlank
{
.per_stream_pstate_method = { dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_vblank, dml2_pstate_method_na },
@@ -149,6 +152,7 @@ static const struct dml2_pmo_pstate_strategy base_strategy_list_4_display[] = {
.allow_state_increase = true,
},
+
// VActive + 1 VBlank
{
.per_stream_pstate_method = { dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_vactive, dml2_pstate_method_vblank },
@@ -1651,6 +1655,7 @@ 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;
+
return is_config_schedulable(pmo, display_cfg, pstate_strategy);
}
@@ -1980,6 +1985,7 @@ static void reset_display_configuration(struct display_configuation_with_meta *d
}
}
+
static void setup_planes_for_drr_by_mask(struct display_configuation_with_meta *display_config,
struct dml2_pmo_instance *pmo,
int plane_mask)
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 55d2464365d0..4d687fa86caa 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
@@ -3,8 +3,8 @@
// Copyright 2024 Advanced Micro Devices, Inc.
#include "dml2_pmo_factory.h"
-#include "dml2_pmo_dcn4_fams2.h"
#include "dml2_pmo_dcn3.h"
+#include "dml2_pmo_dcn4_fams2.h"
#include "dml2_external_lib_deps.h"
static bool dummy_init_for_stutter(struct dml2_pmo_init_for_stutter_in_out *in_out)
@@ -37,6 +37,7 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance *
out->optimize_dcc_mcache = pmo_dcn4_fams2_optimize_dcc_mcache;
result = true;
break;
+ case dml2_project_dcn40:
case dml2_project_dcn4x_stage2:
out->initialize = pmo_dcn3_initialize;
@@ -56,6 +57,7 @@ bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance *
result = true;
break;
+ case dml2_project_dcn42:
case dml2_project_dcn4x_stage2_auto_drr_svp:
out->initialize = pmo_dcn4_fams2_initialize;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.h b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.h
index b90f6263cd85..7218de1824cc 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.h
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_pmo/dml2_pmo_factory.h
@@ -10,4 +10,4 @@
bool dml2_pmo_create(enum dml2_project_id project_id, struct dml2_pmo_instance *out);
-#endif \ No newline at end of file
+#endif
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 5a33e2f357f4..a6c5031f69c1 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
@@ -17,6 +17,8 @@ bool dml2_initialize_instance(struct dml2_initialize_instance_in_out *in_out)
case dml2_project_dcn4x_stage1:
case dml2_project_dcn4x_stage2:
case dml2_project_dcn4x_stage2_auto_drr_svp:
+ case dml2_project_dcn40:
+ case dml2_project_dcn42:
return dml2_top_soc15_initialize_instance(in_out);
case dml2_project_invalid:
default:
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_legacy.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_legacy.c
index 5e14d85821e2..0e3177fe9d27 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_legacy.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml21/src/dml2_top/dml2_top_legacy.c
@@ -3,7 +3,6 @@
// Copyright 2024 Advanced Micro Devices, Inc.
#include "dml2_top_legacy.h"
-#include "dml2_top_soc15.h"
#include "dml2_core_factory.h"
#include "dml2_pmo_factory.h"
#include "display_mode_core_structs.h"
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 a6bd75f30d20..d328d92240b4 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
@@ -410,6 +410,7 @@ struct dml2_core_mode_support_in_out {
} legacy;
};
+
struct dml2_core_mode_programming_in_out {
/*
* Inputs
@@ -501,6 +502,7 @@ struct dml2_core_instance {
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);
+
struct {
struct dml2_core_internal_display_mode_lib mode_lib;
} clean_me_up;
@@ -753,6 +755,7 @@ 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);
+
struct dml2_pmo_init_data init_data;
struct dml2_pmo_scratch scratch;
};
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c
index 4cfe64aa8492..6ef93c6fc1cd 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_dc_resource_mgmt.c
@@ -35,7 +35,7 @@
#define MAX_MPCC_FACTOR 4
struct dc_plane_pipe_pool {
- int pipes_assigned_to_plane[MAX_ODM_FACTOR][MAX_MPCC_FACTOR];
+ unsigned int pipes_assigned_to_plane[MAX_ODM_FACTOR][MAX_MPCC_FACTOR];
bool pipe_used[MAX_ODM_FACTOR][MAX_MPCC_FACTOR];
int num_pipes_assigned_to_plane_for_mpcc_combine;
int num_pipes_assigned_to_plane_for_odm_combine;
@@ -143,7 +143,7 @@ static unsigned int find_pipes_assigned_to_plane(struct dml2_context *ctx,
{
int i;
unsigned int num_found = 0;
- unsigned int plane_id_assigned_to_pipe = -1;
+ unsigned int plane_id_assigned_to_pipe = UINT_MAX;
for (i = 0; i < ctx->config.dcn_pipe_count; i++) {
struct pipe_ctx *pipe = &state->res_ctx.pipe_ctx[i];
@@ -340,8 +340,8 @@ static bool is_pipe_in_candidate_array(const unsigned int pipe_idx,
static bool find_more_pipes_for_stream(struct dml2_context *ctx,
struct dc_state *state, // The state we want to find a free mapping in
unsigned int stream_id, // The stream we want this pipe to drive
- int *assigned_pipes,
- int *assigned_pipe_count,
+ unsigned int *assigned_pipes,
+ unsigned int *assigned_pipe_count,
int pipes_needed,
const struct dc_state *existing_state) // The state (optional) that we want to minimize remapping relative to
{
@@ -366,7 +366,8 @@ static bool find_more_pipes_for_stream(struct dml2_context *ctx,
if (!is_plane_using_pipe(pipe)) {
pipes_needed--;
// TODO: This doens't make sense really, pipe_idx should always be valid
- pipe->pipe_idx = preferred_pipe_candidates[i];
+ ASSERT(preferred_pipe_candidates[i] <= 0xFF);
+ pipe->pipe_idx = (uint8_t)preferred_pipe_candidates[i];
assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx;
}
}
@@ -382,7 +383,8 @@ static bool find_more_pipes_for_stream(struct dml2_context *ctx,
if (!is_plane_using_pipe(pipe)) {
pipes_needed--;
// TODO: This doens't make sense really, pipe_idx should always be valid
- pipe->pipe_idx = i;
+ ASSERT(i >= 0 && i <= 0xFF);
+ pipe->pipe_idx = (uint8_t)i;
assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx;
}
}
@@ -393,7 +395,8 @@ static bool find_more_pipes_for_stream(struct dml2_context *ctx,
if (!is_plane_using_pipe(pipe)) {
pipes_needed--;
// TODO: This doens't make sense really, pipe_idx should always be valid
- pipe->pipe_idx = last_resort_pipe_candidates[i];
+ ASSERT(last_resort_pipe_candidates[i] <= 0xFF);
+ pipe->pipe_idx = (uint8_t)last_resort_pipe_candidates[i];
assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx;
}
}
@@ -406,8 +409,8 @@ static bool find_more_pipes_for_stream(struct dml2_context *ctx,
static bool find_more_free_pipes(struct dml2_context *ctx,
struct dc_state *state, // The state we want to find a free mapping in
unsigned int stream_id, // The stream we want this pipe to drive
- int *assigned_pipes,
- int *assigned_pipe_count,
+ unsigned int *assigned_pipes,
+ unsigned int *assigned_pipe_count,
int pipes_needed,
const struct dc_state *existing_state) // The state (optional) that we want to minimize remapping relative to
{
@@ -432,7 +435,8 @@ static bool find_more_free_pipes(struct dml2_context *ctx,
if (is_pipe_free(pipe)) {
pipes_needed--;
// TODO: This doens't make sense really, pipe_idx should always be valid
- pipe->pipe_idx = preferred_pipe_candidates[i];
+ ASSERT(preferred_pipe_candidates[i] <= 0xFF);
+ pipe->pipe_idx = (uint8_t)preferred_pipe_candidates[i];
assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx;
}
}
@@ -448,7 +452,8 @@ static bool find_more_free_pipes(struct dml2_context *ctx,
if (is_pipe_free(pipe)) {
pipes_needed--;
// TODO: This doens't make sense really, pipe_idx should always be valid
- pipe->pipe_idx = i;
+ ASSERT(i >= 0 && i <= 0xFF);
+ pipe->pipe_idx = (uint8_t)i;
assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx;
}
}
@@ -459,7 +464,8 @@ static bool find_more_free_pipes(struct dml2_context *ctx,
if (is_pipe_free(pipe)) {
pipes_needed--;
// TODO: This doens't make sense really, pipe_idx should always be valid
- pipe->pipe_idx = last_resort_pipe_candidates[i];
+ ASSERT(last_resort_pipe_candidates[i] <= 0xFF);
+ pipe->pipe_idx = (uint8_t)last_resort_pipe_candidates[i];
assigned_pipes[(*assigned_pipe_count)++] = pipe->pipe_idx;
}
}
@@ -909,10 +915,10 @@ static unsigned int get_source_mpc_factor(const struct dml2_context *ctx,
const struct dc_plane_state *plane)
{
struct pipe_ctx *dpp_pipes[MAX_PIPES] = {0};
- int dpp_pipe_count = ctx->config.callbacks.get_dpp_pipes_for_plane(plane,
- &state->res_ctx, dpp_pipes);
- ASSERT(dpp_pipe_count > 0);
+ if (ctx->config.callbacks.get_dpp_pipes_for_plane(plane, &state->res_ctx, dpp_pipes) <= 0)
+ ASSERT(false);
+
return ctx->config.callbacks.get_mpc_slice_count(dpp_pipes[0]);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c
index 66040c877d68..9bbe4e058be7 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_mall_phantom.c
@@ -357,7 +357,7 @@ static bool enough_pipes_for_subvp(struct dml2_context *ctx, struct dc_state *st
*/
static bool subvp_subvp_schedulable(struct dml2_context *ctx, struct dc_state *context)
{
- struct pipe_ctx *subvp_pipes[2];
+ struct pipe_ctx *subvp_pipes[2] = { NULL, NULL };
struct dc_stream_state *phantom = NULL;
uint32_t microschedule_lines = 0;
uint32_t index = 0;
@@ -369,6 +369,9 @@ static bool subvp_subvp_schedulable(struct dml2_context *ctx, struct dc_state *c
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
uint32_t time_us = 0;
+ if (pipe == NULL || pipe->stream == NULL)
+ continue;
+
/* Loop to calculate the maximum microschedule time between the two SubVP pipes,
* and also to store the two main SubVP pipe pointers in subvp_pipes[2].
*/
@@ -386,14 +389,19 @@ static bool subvp_subvp_schedulable(struct dml2_context *ctx, struct dc_state *c
if (time_us > max_microschedule_us)
max_microschedule_us = time_us;
- subvp_pipes[index] = pipe;
- index++;
+ if (index < 2)
+ subvp_pipes[index++] = pipe;
// Maximum 2 SubVP pipes
if (index == 2)
break;
}
}
+
+ /* Minimal guard to avoid C6001 before subvp_pipes[0]/[1] dereference */
+ if (index < 2 || !subvp_pipes[0] || !subvp_pipes[1])
+ return false;
+
vactive1_us = ((subvp_pipes[0]->stream->timing.v_addressable * subvp_pipes[0]->stream->timing.h_total) /
(double)(subvp_pipes[0]->stream->timing.pix_clk_100hz * 100)) * 1000000;
vactive2_us = ((subvp_pipes[1]->stream->timing.v_addressable * subvp_pipes[1]->stream->timing.h_total) /
@@ -459,6 +467,11 @@ bool dml2_svp_drr_schedulable(struct dml2_context *ctx, struct dc_state *context
break;
}
+ if (pipe == NULL || pipe->stream == NULL) {
+ // Defensive: should never happen, try to catch in debug
+ ASSERT(0);
+ return false;
+ }
phantom_stream = ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(context, pipe->stream);
main_timing = &pipe->stream->timing;
phantom_timing = &phantom_stream->timing;
@@ -542,13 +555,21 @@ static bool subvp_vblank_schedulable(struct dml2_context *ctx, struct dc_state *
if (!found && pipe_mall_type == SUBVP_NONE) {
// Found pipe which is not SubVP or Phantom (i.e. the VBLANK pipe).
- vblank_index = i;
+ ASSERT(i <= 0xFF);
+ vblank_index = (uint8_t)i;
found = true;
}
if (!subvp_pipe && pipe_mall_type == SUBVP_MAIN)
subvp_pipe = pipe;
}
+
+ if (subvp_pipe == NULL) {
+ // Defensive: should never happen, catch in debug
+ ASSERT(0);
+ return false;
+ }
+
// Use ignore_msa_timing_param flag to identify as DRR
if (found && context->res_ctx.pipe_ctx[vblank_index].stream->ignore_msa_timing_param) {
// SUBVP + DRR case
@@ -753,6 +774,12 @@ static void enable_phantom_plane(struct dml2_context *ctx,
return;
}
+ /* Minimal NULL guard for C6011 */
+ if (!phantom_plane) {
+ ASSERT(0);
+ continue;
+ }
+
memcpy(&phantom_plane->address, &curr_pipe->plane_state->address, sizeof(phantom_plane->address));
memcpy(&phantom_plane->scaling_quality, &curr_pipe->plane_state->scaling_quality,
sizeof(phantom_plane->scaling_quality));
@@ -880,6 +907,11 @@ bool dml2_svp_add_phantom_pipe_to_dc_state(struct dml2_context *ctx, struct dc_s
if (ctx->config.svp_pstate.force_disable_subvp)
return false;
+ if (!state) {
+ ASSERT(0);
+ return false;
+ }
+
if (!all_pipes_have_stream_and_plane(ctx, state))
return false;
@@ -898,6 +930,10 @@ bool dml2_svp_add_phantom_pipe_to_dc_state(struct dml2_context *ctx, struct dc_s
}
if (enough_pipes_for_subvp(ctx, state) && assign_subvp_pipe(ctx, state, &dc_pipe_idx)) {
+ if (state->res_ctx.pipe_ctx[dc_pipe_idx].stream == NULL) {
+ ASSERT(0);
+ return false;
+ }
dml_pipe_idx = dml2_helper_find_dml_pipe_idx_by_stream_id(ctx, state->res_ctx.pipe_ctx[dc_pipe_idx].stream->stream_id);
svp_height = mode_support_info->SubViewportLinesNeededInMALL[dml_pipe_idx];
vstartup = dml_get_vstartup_calculated(&ctx->v20.dml_core_ctx, dml_pipe_idx);
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c
index d834cb595afa..cf3a69aba638 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_translation_helper.c
@@ -330,8 +330,8 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc,
{
struct dml2_policy_build_synthetic_soc_states_scratch *s = &dml2->v20.scratch.create_scratch.build_synthetic_socbb_scratch;
struct dml2_policy_build_synthetic_soc_states_params *p = &dml2->v20.scratch.build_synthetic_socbb_params;
- unsigned int dcfclk_stas_mhz[NUM_DCFCLK_STAS] = {0};
- unsigned int dcfclk_stas_mhz_new[NUM_DCFCLK_STAS_NEW] = {0};
+ int dcfclk_stas_mhz[NUM_DCFCLK_STAS] = {0};
+ int dcfclk_stas_mhz_new[NUM_DCFCLK_STAS_NEW] = {0};
unsigned int dml_project = dml2->v20.dml_core_ctx.project;
unsigned int i = 0;
@@ -765,7 +765,7 @@ static void populate_dml_timing_cfg_from_stream_state(struct dml_timing_cfg_st *
out->PixelClock[location] *= 2;
out->HTotal[location] = in->timing.h_total;
out->VTotal[location] = in->timing.v_total;
- out->Interlace[location] = in->timing.flags.INTERLACE;
+ out->Interlace[location] = (in->timing.flags.INTERLACE != 0);
hblank_start = in->timing.h_total - in->timing.h_front_porch;
out->HBlankEnd[location] = hblank_start
- in->timing.h_addressable
@@ -1174,12 +1174,12 @@ static unsigned int map_plane_to_dml_display_cfg(const struct dml2_context *dml2
const struct dc_state *context, const struct dml_display_cfg_st *dml_dispcfg, unsigned int stream_id, int plane_index)
{
unsigned int plane_id;
- int i = 0;
- int location = -1;
+ unsigned int i = 0;
+ unsigned int location = UINT_MAX;
if (!get_plane_id(context->bw_ctx.dml2, context, plane, stream_id, plane_index, &plane_id)) {
ASSERT(false);
- return -1;
+ return UINT_MAX;
}
for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c
index 9a33158b63bf..6c7cdf102906 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_utils.c
@@ -255,7 +255,8 @@ static void populate_pipe_ctx_dlg_params_from_dml(struct pipe_ctx *pipe_ctx, str
pipe_ctx->pipe_dlg_param.vupdate_width = dml_get_vupdate_width(mode_lib, pipe_idx);
pipe_ctx->pipe_dlg_param.vready_offset = dml_get_vready_offset(mode_lib, pipe_idx);
- pipe_ctx->pipe_dlg_param.otg_inst = pipe_ctx->stream_res.tg->inst;
+ ASSERT(pipe_ctx->stream_res.tg->inst >= 0 && pipe_ctx->stream_res.tg->inst <= 0xFF);
+ pipe_ctx->pipe_dlg_param.otg_inst = (unsigned char)pipe_ctx->stream_res.tg->inst;
pipe_ctx->pipe_dlg_param.hactive = hactive;
pipe_ctx->pipe_dlg_param.vactive = vactive;
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c
index 307186eb6af0..93b7613fc4f2 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper.c
@@ -6,8 +6,24 @@
*/
#include "dml2_internal_types.h"
+#include "dml2_wrapper.h"
#include "dml2_wrapper_fpu.h"
+#include "dml21_wrapper.h"
+#include "dml21_wrapper_fpu.h"
+#include "dc_fpu.h"
+
+#if !defined(DC_RUN_WITH_PREEMPTION_ENABLED)
+#define DC_RUN_WITH_PREEMPTION_ENABLED(code) code
+#endif // !DC_RUN_WITH_PREEMPTION_ENABLED
+
+struct dml2_context *dml2_allocate_memory(void)
+{
+ struct dml2_context *dml2;
+
+ DC_RUN_WITH_PREEMPTION_ENABLED(dml2 = vzalloc(sizeof(struct dml2_context)));
+ return dml2;
+}
bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2_context *dml2,
enum dc_validate_mode validate_mode)
{
@@ -23,16 +39,12 @@ bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2
return out;
}
- DC_FP_START();
-
/* Use dml_validate_only for DC_VALIDATE_MODE_ONLY and DC_VALIDATE_MODE_AND_STATE_INDEX path */
if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
out = dml2_validate_only(context, validate_mode);
else
out = dml2_validate_and_build_resource(in_dc, context, validate_mode);
- DC_FP_END();
-
return out;
}
@@ -70,22 +82,20 @@ static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_op
break;
}
- DC_FP_START();
-
initialize_dml2_ip_params(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.ip);
initialize_dml2_soc_bbox(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.soc);
initialize_dml2_soc_states(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.soc, &(*dml2)->v20.dml_core_ctx.states);
- DC_FP_END();
}
bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2)
{
// TODO : Temporarily add DCN_VERSION_3_2 for N-1 validation. Remove DCN_VERSION_3_2 after N-1 validation phase is complete.
- if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version >= DCN_VERSION_4_01))
+ if ((in_dc->debug.using_dml21) && (in_dc->ctx->dce_version >= DCN_VERSION_4_01)) {
return dml21_create(in_dc, dml2, config);
+ }
// Allocate Mode Lib Ctx
*dml2 = dml2_allocate_memory();
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 9a9c27962f68..5ee489682f2e 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
@@ -239,6 +239,7 @@ struct dml2_configuration_options {
bool use_clock_dc_limits;
bool gpuvm_enable;
+ bool hostvm_enable;
bool force_tdlut_enable;
void *bb_from_dmub;
};
diff --git a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c
index 203eef747262..66624cfc27b1 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2_0/dml2_wrapper_fpu.c
@@ -31,8 +31,10 @@
#include "dml2_translation_helper.h"
#include "dml2_mall_phantom.h"
#include "dml2_dc_resource_mgmt.h"
-#include "dml21_wrapper.h"
+#include "dml2_wrapper.h"
#include "dml2_wrapper_fpu.h"
+#include "dml21_wrapper.h"
+#include "dml21_wrapper_fpu.h"
void initialize_dml2_ip_params(struct dml2_context *dml2, const struct dc *in_dc, struct ip_params_st *out)
{
@@ -546,11 +548,6 @@ void dml2_apply_debug_options(const struct dc *dc, struct dml2_context *dml2)
}
}
-inline struct dml2_context *dml2_allocate_memory(void)
-{
- return (struct dml2_context *) vzalloc(sizeof(struct dml2_context));
-}
-
void dml2_destroy(struct dml2_context *dml2)
{
if (!dml2)
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/Makefile b/drivers/gpu/drm/amd/display/dc/dpp/Makefile
index 8324a56fe7db..2595b2504f9d 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dpp/Makefile
@@ -1,5 +1,5 @@
-# Copyright 2022 Advanced Micro Devices, Inc.
+# Copyright 2022-2026 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -80,4 +80,12 @@ AMD_DAL_DPP_DCN401 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn401/,$(DPP_DCN401))
AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN401)
+###############################################################################
+# DCN42
+###############################################################################
+DPP_DCN42 = dcn42_dpp.o
+
+AMD_DAL_DPP_DCN42 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn42/,$(DPP_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN42)
endif
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c
index ce91e5d28956..ef605e0a75e3 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c
@@ -172,10 +172,14 @@ bool dpp1_get_optimal_number_of_taps(
scl_data->taps.h_taps_c = in_taps->h_taps_c;
if (!dpp->ctx->dc->debug.always_scale) {
- if (IDENTITY_RATIO(scl_data->ratios.horz))
+ if (IDENTITY_RATIO(scl_data->ratios.horz)) {
scl_data->taps.h_taps = 1;
- if (IDENTITY_RATIO(scl_data->ratios.vert))
+ scl_data->taps.h_taps_c = 1;
+ }
+ if (IDENTITY_RATIO(scl_data->ratios.vert)) {
scl_data->taps.v_taps = 1;
+ scl_data->taps.v_taps_c = 1;
+ }
if (IDENTITY_RATIO(scl_data->ratios.horz_c))
scl_data->taps.h_taps_c = 1;
if (IDENTITY_RATIO(scl_data->ratios.vert_c))
@@ -284,6 +288,7 @@ void dpp1_cnv_setup (
enum dc_color_space input_color_space,
struct cnv_alpha_2bit_lut *alpha_2bit_lut)
{
+ (void)alpha_2bit_lut;
uint32_t pixel_format;
uint32_t alpha_en;
enum pixel_format_description fmt ;
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c
index 808bca9fb804..0d2c9fcd3362 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp_dscl.c
@@ -102,7 +102,7 @@ static int dpp1_dscl_get_pixel_depth_val(enum lb_pixel_depth depth)
}
}
-static bool dpp1_dscl_is_video_format(enum pixel_format format)
+static bool dpp1_dscl_is_video_format(enum dc_pixel_format format)
{
if (format >= PIXEL_FORMAT_VIDEO_BEGIN
&& format <= PIXEL_FORMAT_VIDEO_END)
@@ -111,7 +111,7 @@ static bool dpp1_dscl_is_video_format(enum pixel_format format)
return false;
}
-static bool dpp1_dscl_is_420_format(enum pixel_format format)
+static bool dpp1_dscl_is_420_format(enum dc_pixel_format format)
{
if (format == PIXEL_FORMAT_420BPP8 ||
format == PIXEL_FORMAT_420BPP10)
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c
index c433f4b876e9..8d5000790904 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c
@@ -92,7 +92,10 @@ void dpp2_power_on_obuf(
void dpp2_dummy_program_input_lut(
struct dpp *dpp_base,
const struct dc_gamma *gamma)
-{}
+{
+ (void)dpp_base;
+ (void)gamma;
+}
static void dpp2_cnv_setup (
struct dpp *dpp_base,
@@ -369,7 +372,11 @@ void oppn20_dummy_program_regamma_pwl(
struct dpp *dpp,
const struct pwl_params *params,
enum opp_regamma mode)
-{}
+{
+ (void)dpp;
+ (void)params;
+ (void)mode;
+}
static struct dpp_funcs dcn20_dpp_funcs = {
.dpp_read_state = dpp20_read_state,
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c
index 31613372e214..26f9485f165d 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp_cm.c
@@ -1016,6 +1016,7 @@ static void dpp20_set_3dlut_mode(
bool is_color_channel_12bits,
bool is_lut_size17x17x17)
{
+ (void)is_color_channel_12bits;
uint32_t lut_mode;
struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c
index c7923531da83..e7880fc61b4a 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c
@@ -524,10 +524,14 @@ bool dpp3_get_optimal_number_of_taps(
scl_data->taps.v_taps_c = max_taps_c;
if (!dpp->ctx->dc->debug.always_scale) {
- if (IDENTITY_RATIO(scl_data->ratios.horz))
+ if (IDENTITY_RATIO(scl_data->ratios.horz)) {
scl_data->taps.h_taps = 1;
- if (IDENTITY_RATIO(scl_data->ratios.vert))
+ scl_data->taps.h_taps_c = 1;
+ }
+ if (IDENTITY_RATIO(scl_data->ratios.vert)) {
scl_data->taps.v_taps = 1;
+ scl_data->taps.v_taps_c = 1;
+ }
if (IDENTITY_RATIO(scl_data->ratios.horz_c))
scl_data->taps.h_taps_c = 1;
if (IDENTITY_RATIO(scl_data->ratios.vert_c))
@@ -1303,6 +1307,7 @@ static void dpp3_set_3dlut_mode(
bool is_color_channel_12bits,
bool is_lut_size17x17x17)
{
+ (void)is_color_channel_12bits;
uint32_t lut_mode;
struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c
index 82eca0e7b7d0..8170a86ad0ea 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp_cm.c
@@ -80,6 +80,7 @@ static void dpp3_program_gammcor_lut(
uint32_t num,
bool is_ram_a)
{
+ (void)is_ram_a;
uint32_t i;
struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base);
uint32_t last_base_value_red = rgb[num-1].red_reg + rgb[num-1].delta_red_reg;
@@ -132,6 +133,8 @@ static void dpp3_power_on_gamcor_lut(
if (dpp_base->ctx->dc->debug.enable_mem_low_power.bits.cm) {
if (power_on) {
REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, 0);
+ if (dpp_base->ctx->dc->caps.ips_v2_support)
+ REG_UPDATE(CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_DIS, 1);
REG_WAIT(CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, 0, 1, 5);
} else {
dpp_base->ctx->dc->optimized_required = true;
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 58b9f1cd0825..debcf308cb3b 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
@@ -1,4 +1,5 @@
-/* Copyright 2023 Advanced Micro Devices, Inc.
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2023-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -653,6 +654,8 @@
struct dcn401_dpp_registers {
DPP_REG_VARIABLE_LIST_DCN401;
+ uint32_t ALPHA_2BIT_LUT01;
+ uint32_t ALPHA_2BIT_LUT23;
};
struct dcn401_dpp_shift {
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c
index 62bf7cea21d8..821d5173b59f 100644
--- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_cm.c
@@ -132,6 +132,9 @@ void dpp401_set_cursor_position(
uint32_t width,
uint32_t height)
{
+ (void)param;
+ (void)width;
+ (void)height;
struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
uint32_t cur_en = pos->enable ? 1 : 0;
@@ -237,6 +240,8 @@ void dpp401_set_cursor_matrix(
enum dc_color_space color_space,
struct dc_csc_transform cursor_csc_color_matrix)
{
+ (void)color_space;
+ (void)cursor_csc_color_matrix;
//Since we don't have cursor matrix information, force bypass mode by passing in unknown color space
dpp401_program_cursor_csc(dpp_base, COLOR_SPACE_UNKNOWN, NULL);
}
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 a62c4733ed3b..8b7e55e337d3 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
@@ -94,7 +94,7 @@ static int dpp401_dscl_get_pixel_depth_val(enum lb_pixel_depth depth)
}
}
-static bool dpp401_dscl_is_video_format(enum pixel_format format)
+static bool dpp401_dscl_is_video_format(enum dc_pixel_format format)
{
if (format >= PIXEL_FORMAT_VIDEO_BEGIN
&& format <= PIXEL_FORMAT_VIDEO_END)
@@ -103,7 +103,7 @@ static bool dpp401_dscl_is_video_format(enum pixel_format format)
return false;
}
-static bool dpp401_dscl_is_420_format(enum pixel_format format)
+static bool dpp401_dscl_is_420_format(enum dc_pixel_format format)
{
if (format == PIXEL_FORMAT_420BPP8 ||
format == PIXEL_FORMAT_420BPP10)
@@ -155,7 +155,12 @@ static void dpp401_power_on_dscl(
if (dpp->tf_regs->DSCL_MEM_PWR_CTRL) {
if (power_on) {
REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, 0);
- REG_WAIT(DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, 0, 1, 5);
+ if (dpp->base.ctx->dc->caps.ips_v2_support) {
+ /*hw default changes to LS*/
+ REG_UPDATE(DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_DIS, 1);
+ REG_WAIT(DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, 0, 1, 100);
+ } else
+ REG_WAIT(DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, 0, 1, 5);
} else {
if (dpp->base.ctx->dc->debug.enable_mem_low_power.bits.dscl) {
dpp->base.ctx->dc->optimized_required = true;
@@ -956,6 +961,15 @@ static void dpp401_dscl_program_isharp(struct dpp *dpp_base,
*bs_coeffs_updated = false;
PERF_TRACE();
+ /*power on isharp_delta_mem first*/
+ if (dpp_base->ctx->dc->caps.ips_v2_support) {
+ /*HW default is LS, need to wake up*/
+ REG_UPDATE_2(ISHARP_DELTA_LUT_MEM_PWR_CTRL,
+ ISHARP_DELTA_LUT_MEM_PWR_FORCE, 0,
+ ISHARP_DELTA_LUT_MEM_PWR_DIS, 1);
+ REG_WAIT(ISHARP_DELTA_LUT_MEM_PWR_CTRL,
+ ISHARP_DELTA_LUT_MEM_PWR_STATE, 0, 1, 100);
+ }
/* ISHARP_MODE */
REG_SET_6(ISHARP_MODE, 0,
ISHARP_EN, scl_data->dscl_prog_data.isharp_en,
@@ -1033,6 +1047,13 @@ static void dpp401_dscl_program_isharp(struct dpp *dpp_base,
}
}
+ /*power on isharp_delta_mem first*/
+ if (dpp_base->ctx->dc->caps.ips_v2_support) {
+ /*HW default is LS, need to wake up*/
+ REG_UPDATE_SEQ_2(ISHARP_DELTA_LUT_MEM_PWR_CTRL,
+ ISHARP_DELTA_LUT_MEM_PWR_FORCE, 0,
+ ISHARP_DELTA_LUT_MEM_PWR_DIS, 0);
+ }
PERF_TRACE();
} // dpp401_dscl_program_isharp
/**
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c
new file mode 100644
index 000000000000..c126fb9d5bfa
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c
@@ -0,0 +1,333 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dm_services.h"
+#include "core_types.h"
+#include "reg_helper.h"
+#include "dcn42_dpp.h"
+#include "dcn35/dcn35_dpp.h"
+
+#define REG(reg)\
+ dpp->tf_regs->reg
+
+#define CTX \
+ dpp->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+ dpp->tf_shift->field_name, dpp->tf_mask->field_name
+
+static const uint32_t *get_hist_rgb_luma_coefs(enum dc_color_space color_space)
+{
+ // Coefs in s.6.12.
+ // Y = 0.2126R + 0.7152G + 0.0722B
+ static const uint32_t luma_transform_bt_709[] = {0x1cb36, 0x1e6e2, 0x1b27b};
+ // Y = 0.2627R + 0.678G + 0.0593B
+ static const uint32_t luma_transform_bt_2020[] = {0x1d0d0, 0x1e5b2, 0x1ae5c};
+
+ switch (color_space) {
+ case COLOR_SPACE_2020_RGB_FULLRANGE:
+ case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
+ return luma_transform_bt_2020;
+ default:
+ return luma_transform_bt_709;
+ }
+}
+
+static void dpp42_dpp_cm_hist_control(
+ struct dpp *dpp_base,
+ struct cm_hist_control cntl,
+ enum dc_color_space color_space)
+{
+ struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base);
+
+ REG_UPDATE_10(
+ CM_HIST_CNTL,
+ CM_HIST_SEL, cntl.tap_point,
+ CM_HIST_CH_EN, cntl.channels_enabled,
+ CM_HIST_SRC1_SEL, cntl.src_1_select,
+ CM_HIST_SRC2_SEL, cntl.src_2_select,
+ CM_HIST_SRC3_SEL, cntl.src_3_select,
+ CM_HIST_CH1_XBAR, cntl.ch1_src,
+ CM_HIST_CH2_XBAR, cntl.ch2_src,
+ CM_HIST_CH3_XBAR, cntl.ch3_src,
+ CM_HIST_FORMAT, cntl.format,
+ CM_HIST_READ_CHANNEL_MASK, cntl.read_channel_mask);
+
+ if (cntl.src_2_select == CM_HIST_SRC2_MODE_RGB_TO_Y) {
+ const uint32_t *luma_transform = get_hist_rgb_luma_coefs(color_space);
+
+ REG_UPDATE(CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, luma_transform[0]);
+ REG_UPDATE(CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, luma_transform[1]);
+ REG_UPDATE(CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, luma_transform[2]);
+ } else {
+ REG_UPDATE(CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, 0);
+ REG_UPDATE(CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, 0x1f000); // 1 in s.6.12
+ REG_UPDATE(CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, 0);
+ }
+}
+
+static bool dpp42_dpp_cm_hist_read(struct dpp *dpp_base, struct cm_hist *hist_out)
+{
+ struct dcn42_dpp *dpp = TO_DCN42_DPP(dpp_base);
+ uint32_t channel_mask = 0;
+ uint32_t rdy_status = 0, rdy_status_a = 0, rdy_status_b = 0;
+ bool ch1, ch2, ch3;
+
+ if (hist_out == NULL)
+ return false;
+
+
+ REG_GET(CM_HIST_CNTL, CM_HIST_READ_CHANNEL_MASK, &channel_mask);
+ ch1 = (channel_mask & 1) > 0;
+ ch2 = (channel_mask & 2) > 0;
+ ch3 = (channel_mask & 4) > 0;
+
+ REG_GET(CM_HIST_STATUS, CM_HIST_BUFA_RDY_STATUS, &rdy_status_a);
+ REG_GET(CM_HIST_STATUS, CM_HIST_BUFB_RDY_STATUS, &rdy_status_b);
+
+ rdy_status = rdy_status_a || rdy_status_b;
+
+ if (rdy_status) {
+ REG_UPDATE(CM_HIST_LOCK, CM_HIST_LOCK, 1);
+ REG_UPDATE(CM_HIST_INDEX, CM_HIST_INDEX, 0);
+ for (int i = 0; i < 256; i++) {
+ uint32_t temp;
+
+ if (ch1) {
+ REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp);
+ hist_out->ch1[i] += temp;
+ }
+ if (ch2) {
+ REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp);
+ hist_out->ch2[i] += temp;
+ }
+ if (ch3) {
+ REG_GET(CM_HIST_DATA, CM_HIST_DATA, &temp);
+ hist_out->ch3[i] += temp;
+ }
+ }
+ REG_UPDATE(CM_HIST_LOCK, CM_HIST_LOCK, 0);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static void dpp42_dpp_setup(
+ struct dpp *dpp_base,
+ enum surface_pixel_format format,
+ enum expansion_mode mode,
+ struct dc_csc_transform input_csc_color_matrix,
+ enum dc_color_space input_color_space,
+ struct cnv_alpha_2bit_lut *alpha_2bit_lut)
+{
+ struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base);
+ uint32_t pixel_format = 0;
+ uint32_t alpha_en = 1;
+ enum dc_color_space color_space = COLOR_SPACE_SRGB;
+ enum dcn10_input_csc_select select = INPUT_CSC_SELECT_BYPASS;
+ uint32_t is_2bit = 0;
+ uint32_t alpha_plane_enable = 0;
+ uint32_t dealpha_en = 0, dealpha_ablnd_en = 0;
+ uint32_t realpha_en = 0, realpha_ablnd_en = 0;
+ struct out_csc_color_matrix tbl_entry;
+ int i;
+
+ REG_SET_2(FORMAT_CONTROL, 0,
+ CNVC_BYPASS, 0,
+ FORMAT_EXPANSION_MODE, mode);
+
+ REG_UPDATE(FORMAT_CONTROL, FORMAT_CNV16, 0);
+ REG_UPDATE(FORMAT_CONTROL, CNVC_BYPASS_MSB_ALIGN, 0);
+ REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE, 0);
+ REG_UPDATE(FORMAT_CONTROL, CLAMP_POSITIVE_C, 0);
+
+ REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_R, 0);
+ REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_G, 1);
+ REG_UPDATE(FORMAT_CONTROL, FORMAT_CROSSBAR_B, 2);
+
+ switch (format) {
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
+ pixel_format = 1;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
+ pixel_format = 3;
+ alpha_en = 0;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
+ pixel_format = 8;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
+ pixel_format = 10;
+ is_2bit = 1;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
+ pixel_format = 65;
+ color_space = COLOR_SPACE_YCBCR709;
+ select = INPUT_CSC_SELECT_ICSC;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
+ pixel_format = 64;
+ color_space = COLOR_SPACE_YCBCR709;
+ select = INPUT_CSC_SELECT_ICSC;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
+ pixel_format = 67;
+ color_space = COLOR_SPACE_YCBCR709;
+ select = INPUT_CSC_SELECT_ICSC;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
+ pixel_format = 66;
+ color_space = COLOR_SPACE_YCBCR709;
+ select = INPUT_CSC_SELECT_ICSC;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616:
+ pixel_format = 26; /* ARGB16161616_UNORM */
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
+ pixel_format = 24;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
+ pixel_format = 25;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888:
+ pixel_format = 12;
+ color_space = COLOR_SPACE_YCBCR709;
+ select = INPUT_CSC_SELECT_ICSC;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX:
+ pixel_format = 112;
+ alpha_en = 0;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX:
+ pixel_format = 113;
+ alpha_en = 0;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010:
+ pixel_format = 114;
+ color_space = COLOR_SPACE_YCBCR709;
+ select = INPUT_CSC_SELECT_ICSC;
+ is_2bit = 1;
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102:
+ pixel_format = 115;
+ color_space = COLOR_SPACE_YCBCR709;
+ select = INPUT_CSC_SELECT_ICSC;
+ is_2bit = 1;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGBE:
+ pixel_format = 116;
+ alpha_plane_enable = 0;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
+ pixel_format = 116;
+ alpha_plane_enable = 1;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT:
+ pixel_format = 118;
+ alpha_en = 0;
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT:
+ pixel_format = 119;
+ alpha_en = 0;
+ break;
+ default:
+ break;
+ }
+
+ /* Set default color space based on format if none is given. */
+ color_space = input_color_space ? input_color_space : color_space;
+
+ if (is_2bit == 1 && alpha_2bit_lut != NULL) {
+ REG_UPDATE(ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT0, alpha_2bit_lut->lut0);
+ REG_UPDATE(ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT1, alpha_2bit_lut->lut1);
+ REG_UPDATE(ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT2, alpha_2bit_lut->lut2);
+ REG_UPDATE(ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT3, alpha_2bit_lut->lut3);
+ }
+
+ REG_SET_2(CNVC_SURFACE_PIXEL_FORMAT, 0,
+ CNVC_SURFACE_PIXEL_FORMAT, pixel_format,
+ CNVC_ALPHA_PLANE_ENABLE, alpha_plane_enable);
+ REG_UPDATE(FORMAT_CONTROL, FORMAT_CONTROL__ALPHA_EN, alpha_en);
+
+ REG_SET_2(PRE_DEALPHA, 0,
+ PRE_DEALPHA_EN, dealpha_en,
+ PRE_DEALPHA_ABLND_EN, dealpha_ablnd_en);
+ REG_SET_2(PRE_REALPHA, 0,
+ PRE_REALPHA_EN, realpha_en,
+ PRE_REALPHA_ABLND_EN, realpha_ablnd_en);
+
+ /* If input adjustment exists, program the ICSC with those values. */
+ if (input_csc_color_matrix.enable_adjustment == true) {
+ for (i = 0; i < 12; i++)
+ tbl_entry.regval[i] = input_csc_color_matrix.matrix[i];
+
+ tbl_entry.color_space = input_color_space;
+
+ if (color_space >= COLOR_SPACE_YCBCR601)
+ select = INPUT_CSC_SELECT_ICSC;
+ else
+ select = INPUT_CSC_SELECT_BYPASS;
+
+ dpp3_program_post_csc(dpp_base, color_space, select,
+ &tbl_entry);
+ } else {
+ dpp3_program_post_csc(dpp_base, color_space, select, NULL);
+ }
+}
+
+static struct dpp_funcs dcn42_dpp_funcs = {
+ .dpp_program_gamcor_lut = dpp3_program_gamcor_lut,
+ .dpp_read_state = dpp401_read_state,
+ .dpp_reset = dpp_reset,
+ .dpp_set_scaler = dpp401_dscl_set_scaler_manual_scale,
+ .dpp_get_optimal_number_of_taps = dpp3_get_optimal_number_of_taps,
+ .dpp_set_pre_degam = dpp3_set_pre_degam,
+ .dpp_setup = dpp42_dpp_setup,
+ .dpp_program_cm_dealpha = dpp3_program_cm_dealpha,
+ .dpp_program_cm_bias = dpp3_program_cm_bias,
+ .dpp_program_bias_and_scale = dpp35_program_bias_and_scale_fcnv,
+ .dpp_cnv_set_alpha_keyer = dpp2_cnv_set_alpha_keyer,
+ .set_cursor_attributes = dpp401_set_cursor_attributes,
+ .set_cursor_position = dpp401_set_cursor_position,
+ .set_optional_cursor_attributes = dpp401_set_optional_cursor_attributes,
+ .dpp_dppclk_control = dpp35_dppclk_control,
+ .dpp_set_hdr_multiplier = dpp3_set_hdr_multiplier,
+ .set_cursor_matrix = dpp401_set_cursor_matrix,
+ .dpp_cm_hist_control = dpp42_dpp_cm_hist_control,
+ .dpp_cm_hist_read = dpp42_dpp_cm_hist_read,
+ .dpp_read_reg_state = dpp30_read_reg_state,
+};
+
+
+static struct dpp_caps dcn42_dpp_cap = {
+ .dscl_data_proc_format = DSCL_DATA_PRCESSING_FLOAT_FORMAT,
+ .max_lb_partitions = 63,
+ .dscl_calc_lb_num_partitions = dscl401_calc_lb_num_partitions,
+};
+
+bool dpp42_construct(
+ struct dcn42_dpp *dpp,
+ struct dc_context *ctx,
+ uint32_t inst,
+ const struct dcn42_dpp_registers *tf_regs,
+ const struct dcn42_dpp_shift *tf_shift,
+ const struct dcn42_dpp_mask *tf_mask)
+{
+ dpp->base.ctx = ctx;
+
+ dpp->base.inst = inst;
+ dpp->base.funcs = &dcn42_dpp_funcs;
+ dpp->base.caps = &dcn42_dpp_cap;
+
+ dpp->tf_regs = tf_regs;
+ dpp->tf_shift = tf_shift;
+ dpp->tf_mask = tf_mask;
+
+ return true;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h
new file mode 100644
index 000000000000..f4ee419eabf7
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.h
@@ -0,0 +1,469 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2026 Advanced Micro Devices, Inc. */
+
+#ifndef __DCN42_DPP_H__
+#define __DCN42_DPP_H__
+
+#include "dcn401/dcn401_dpp.h"
+
+#define TO_DCN42_DPP(dpp)\
+ container_of(dpp, struct dcn42_dpp, base)
+
+#define DPP_REG_LIST_SH_MASK_DCN42_COMMON(mask_sh)\
+ TF_SF(CM0_CM_MEM_PWR_STATUS, GAMCOR_MEM_PWR_STATE, mask_sh),\
+ TF_SF(CM0_CM_DEALPHA, CM_DEALPHA_EN, mask_sh),\
+ TF_SF(CM0_CM_DEALPHA, CM_DEALPHA_ABLND, mask_sh),\
+ TF_SF(CM0_CM_BIAS_CR_R, CM_BIAS_CR_R, mask_sh),\
+ TF_SF(CM0_CM_BIAS_Y_G_CB_B, CM_BIAS_Y_G, mask_sh),\
+ TF_SF(CM0_CM_BIAS_Y_G_CB_B, CM_BIAS_CB_B, mask_sh),\
+ TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_DIS, mask_sh),\
+ TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_FORCE, mask_sh),\
+ TF_SF(CM0_CM_MEM_PWR_CTRL, GAMCOR_MEM_PWR_DIS, mask_sh),\
+ TF_SF(CNVC_CFG0_PRE_DEGAM, PRE_DEGAM_MODE, mask_sh),\
+ TF_SF(CNVC_CFG0_PRE_DEGAM, PRE_DEGAM_SELECT, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_MODE, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_PWL_DISABLE, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_MODE_CURRENT, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_CONTROL, CM_GAMCOR_SELECT_CURRENT, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_LUT_INDEX, CM_GAMCOR_LUT_INDEX, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_LUT_DATA, CM_GAMCOR_LUT_DATA, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_WRITE_COLOR_MASK, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_READ_COLOR_SEL, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_READ_DBG, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_HOST_SEL, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_LUT_CONTROL, CM_GAMCOR_LUT_CONFIG_MODE, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_RAMA_START_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_B, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_RAMA_START_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_RAMA_START_SLOPE_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_RAMA_START_BASE_CNTL_B, CM_GAMCOR_RAMA_EXP_REGION_START_BASE_B, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL1_B, CM_GAMCOR_RAMA_EXP_REGION_END_BASE_B, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL2_B, CM_GAMCOR_RAMA_EXP_REGION_END_B, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_RAMA_END_CNTL2_B, CM_GAMCOR_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_RAMA_OFFSET_B, CM_GAMCOR_RAMA_OFFSET_B, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\
+ TF_SF(CM0_CM_GAMCOR_RAMA_REGION_0_1, CM_GAMCOR_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
+ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh),\
+ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh),\
+ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh),\
+ TF_SF(DSCL0_DSCL_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh),\
+ TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_START, mask_sh),\
+ TF_SF(DSCL0_OTG_H_BLANK, OTG_H_BLANK_END, mask_sh),\
+ TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_START, mask_sh),\
+ TF_SF(DSCL0_OTG_V_BLANK, OTG_V_BLANK_END, mask_sh),\
+ TF_SF(DSCL0_LB_DATA_FORMAT, INTERLEAVE_EN, mask_sh),\
+ TF2_SF(DSCL0, LB_DATA_FORMAT__ALPHA_EN, mask_sh),\
+ TF_SF(DSCL0_LB_MEMORY_CTRL, MEMORY_CONFIG, mask_sh),\
+ TF_SF(DSCL0_LB_MEMORY_CTRL, LB_MAX_PARTITIONS, mask_sh),\
+ TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_MODE, mask_sh),\
+ TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_NUM_PIPE, mask_sh),\
+ TF_SF(DSCL0_DSCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh),\
+ TF_SF(DSCL0_DSCL_AUTOCAL, AUTOCAL_PIPE_ID, mask_sh),\
+ TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS, mask_sh),\
+ TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS, mask_sh),\
+ TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_V_NUM_TAPS_C, mask_sh),\
+ TF_SF(DSCL0_SCL_TAP_CONTROL, SCL_H_NUM_TAPS_C, mask_sh),\
+ TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_TAP_PAIR_IDX, mask_sh),\
+ TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_PHASE, mask_sh),\
+ TF_SF(DSCL0_SCL_COEF_RAM_TAP_SELECT, SCL_COEF_RAM_FILTER_TYPE, mask_sh),\
+ TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF, mask_sh),\
+ TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_EVEN_TAP_COEF_EN, mask_sh),\
+ TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF, mask_sh),\
+ TF_SF(DSCL0_SCL_COEF_RAM_TAP_DATA, SCL_COEF_RAM_ODD_TAP_COEF_EN, mask_sh),\
+ TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh),\
+ TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_EN, mask_sh),\
+ TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_H_2TAP_SHARP_FACTOR, mask_sh),\
+ TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh),\
+ TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_EN, mask_sh),\
+ TF_SF(DSCL0_DSCL_2TAP_CONTROL, SCL_V_2TAP_SHARP_FACTOR, mask_sh),\
+ TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT, mask_sh),\
+ TF_SF(DSCL0_SCL_MODE, DSCL_MODE, mask_sh),\
+ TF_SF(DSCL0_RECOUT_START, RECOUT_START_X, mask_sh),\
+ TF_SF(DSCL0_RECOUT_START, RECOUT_START_Y, mask_sh),\
+ TF_SF(DSCL0_RECOUT_SIZE, RECOUT_WIDTH, mask_sh),\
+ TF_SF(DSCL0_RECOUT_SIZE, RECOUT_HEIGHT, mask_sh),\
+ TF_SF(DSCL0_MPC_SIZE, MPC_WIDTH, mask_sh),\
+ TF_SF(DSCL0_MPC_SIZE, MPC_HEIGHT, mask_sh),\
+ TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh),\
+ TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh),\
+ TF_SF(DSCL0_SCL_HORZ_FILTER_SCALE_RATIO_C, SCL_H_SCALE_RATIO_C, mask_sh),\
+ TF_SF(DSCL0_SCL_VERT_FILTER_SCALE_RATIO_C, SCL_V_SCALE_RATIO_C, mask_sh),\
+ TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh),\
+ TF_SF(DSCL0_SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh),\
+ TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_FRAC_C, mask_sh),\
+ TF_SF(DSCL0_SCL_HORZ_FILTER_INIT_C, SCL_H_INIT_INT_C, mask_sh),\
+ TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh),\
+ TF_SF(DSCL0_SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh),\
+ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_FRAC_C, mask_sh),\
+ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_C, SCL_V_INIT_INT_C, mask_sh),\
+ TF_SF(DSCL0_SCL_MODE, SCL_CHROMA_COEF_MODE, mask_sh),\
+ TF_SF(DSCL0_SCL_MODE, SCL_COEF_RAM_SELECT_CURRENT, mask_sh), \
+ TF_SF(CNVC_CFG0_PRE_DEALPHA, PRE_DEALPHA_EN, mask_sh), \
+ TF_SF(CNVC_CFG0_PRE_DEALPHA, PRE_DEALPHA_ABLND_EN, mask_sh), \
+ TF_SF(CNVC_CFG0_PRE_REALPHA, PRE_REALPHA_EN, mask_sh), \
+ TF_SF(CNVC_CFG0_PRE_REALPHA, PRE_REALPHA_ABLND_EN, mask_sh), \
+ TF_SF(CNVC_CFG0_PRE_CSC_MODE, PRE_CSC_MODE, mask_sh), \
+ TF_SF(CNVC_CFG0_PRE_CSC_MODE, PRE_CSC_MODE_CURRENT, mask_sh), \
+ TF_SF(CNVC_CFG0_PRE_CSC_C11_C12, PRE_CSC_C11, mask_sh), \
+ TF_SF(CNVC_CFG0_PRE_CSC_C11_C12, PRE_CSC_C12, mask_sh), \
+ TF_SF(CNVC_CFG0_PRE_CSC_C33_C34, PRE_CSC_C33, mask_sh), \
+ TF_SF(CNVC_CFG0_PRE_CSC_C33_C34, PRE_CSC_C34, mask_sh), \
+ TF_SF(CM0_CM_POST_CSC_CONTROL, CM_POST_CSC_MODE, mask_sh), \
+ TF_SF(CM0_CM_POST_CSC_CONTROL, CM_POST_CSC_MODE_CURRENT, mask_sh), \
+ TF_SF(CM0_CM_POST_CSC_C11_C12, CM_POST_CSC_C11, mask_sh), \
+ TF_SF(CM0_CM_POST_CSC_C11_C12, CM_POST_CSC_C12, mask_sh), \
+ TF_SF(CM0_CM_POST_CSC_C33_C34, CM_POST_CSC_C33, mask_sh), \
+ TF_SF(CM0_CM_POST_CSC_C33_C34, CM_POST_CSC_C34, mask_sh), \
+ TF_SF(CM0_CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_INDEX, mask_sh), \
+ TF_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS, mask_sh), \
+ TF2_SF(CNVC_CFG0, FORMAT_CONTROL__ALPHA_EN, mask_sh), \
+ TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_EXPANSION_MODE, mask_sh), \
+ TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_SURFACE_PIXEL_FORMAT, mask_sh), \
+ TF_SF(CNVC_CFG0_CNVC_SURFACE_PIXEL_FORMAT, CNVC_ALPHA_PLANE_ENABLE, mask_sh), \
+ TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_MODE, mask_sh), \
+ TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_EXPANSION_MODE, mask_sh), \
+ TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_ENABLE, mask_sh), \
+ TF_SF(CM_CUR0_CURSOR0_COLOR0, CUR0_COLOR0, mask_sh), \
+ TF_SF(CM_CUR0_CURSOR0_COLOR1, CUR0_COLOR1, mask_sh), \
+ TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y, CUR0_FP_BIAS_G_Y, mask_sh), \
+ TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_G_Y, CUR0_FP_SCALE_G_Y, mask_sh), \
+ TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB, CUR0_FP_BIAS_RB_CRCB, mask_sh), \
+ TF_SF(CM_CUR0_CURSOR0_FP_SCALE_BIAS_RB_CRCB, CUR0_FP_SCALE_RB_CRCB, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_MODE, CUR0_MATRIX_MODE, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_MODE, CUR0_MATRIX_MODE_CURRENT, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_MODE, CUR0_MATRIX_COEF_FORMAT, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_C11_C12_A, CUR0_MATRIX_C11_A, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_C11_C12_A, CUR0_MATRIX_C12_A, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_C13_C14_A, CUR0_MATRIX_C13_A, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_C13_C14_A, CUR0_MATRIX_C14_A, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_C21_C22_A, CUR0_MATRIX_C21_A, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_C21_C22_A, CUR0_MATRIX_C22_A, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_C23_C24_A, CUR0_MATRIX_C23_A, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_C23_C24_A, CUR0_MATRIX_C24_A, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_C31_C32_A, CUR0_MATRIX_C31_A, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_C31_C32_A, CUR0_MATRIX_C32_A, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_C33_C34_A, CUR0_MATRIX_C33_A, mask_sh), \
+ TF_SF(CM_CUR0_CUR0_MATRIX_C33_C34_A, CUR0_MATRIX_C34_A, mask_sh), \
+ TF_SF(DPP_TOP0_DPP_CONTROL, DPP_CLOCK_ENABLE, mask_sh), \
+ TF_SF(CM0_CM_HDR_MULT_COEF, CM_HDR_MULT_COEF, mask_sh), \
+ TF_SF(CM0_CM_CONTROL, CM_BYPASS, mask_sh), \
+ TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SEL, mask_sh), \
+ TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH_EN, mask_sh), \
+ TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SRC1_SEL, mask_sh), \
+ TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SRC2_SEL, mask_sh), \
+ TF_SF(CM0_CM_HIST_CNTL, CM_HIST_SRC3_SEL, mask_sh), \
+ TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH1_XBAR, mask_sh), \
+ TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH2_XBAR, mask_sh), \
+ TF_SF(CM0_CM_HIST_CNTL, CM_HIST_CH3_XBAR, mask_sh), \
+ TF_SF(CM0_CM_HIST_CNTL, CM_HIST_FORMAT, mask_sh), \
+ TF_SF(CM0_CM_HIST_CNTL, CM_HIST_READ_CHANNEL_MASK, mask_sh), \
+ TF_SF(CM0_CM_HIST_LOCK, CM_HIST_LOCK, mask_sh), \
+ TF_SF(CM0_CM_HIST_INDEX, CM_HIST_INDEX, mask_sh), \
+ TF_SF(CM0_CM_HIST_DATA, CM_HIST_DATA, mask_sh), \
+ TF_SF(CM0_CM_HIST_DATA, CM_HIST_DATA, mask_sh), \
+ TF_SF(CM0_CM_HIST_STATUS, CM_HIST_BUFA_RDY_STATUS, mask_sh), \
+ TF_SF(CM0_CM_HIST_STATUS, CM_HIST_BUFB_RDY_STATUS, mask_sh), \
+ TF_SF(CM0_CM_HIST_SCALE_SRC1, CM_HIST_SCALE_SRC1, mask_sh), \
+ TF_SF(CM0_CM_HIST_COEFA_SRC2, CM_HIST_COEFA_SRC2, mask_sh), \
+ TF_SF(CM0_CM_HIST_COEFB_SRC2, CM_HIST_COEFB_SRC2, mask_sh), \
+ TF_SF(CM0_CM_HIST_COEFC_SRC2, CM_HIST_COEFC_SRC2, mask_sh), \
+ TF_SF(CM0_CM_HIST_SCALE_SRC3, CM_HIST_SCALE_SRC3, mask_sh), \
+ TF_SF(CM0_CM_HIST_BIAS_SRC1, CM_HIST_BIAS_SRC1, mask_sh), \
+ TF_SF(CM0_CM_HIST_BIAS_SRC2, CM_HIST_BIAS_SRC2, mask_sh), \
+ TF_SF(CM0_CM_HIST_BIAS_SRC3, CM_HIST_BIAS_SRC3, mask_sh), \
+ TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_MODE, mask_sh), \
+ TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_PITCH, mask_sh), \
+ TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_LINES_PER_CHUNK, mask_sh), \
+ TF_SF(CURSOR0_0_CURSOR_CONTROL, CURSOR_ENABLE, mask_sh), \
+ TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CNV16, mask_sh), \
+ TF_SF(CNVC_CFG0_FORMAT_CONTROL, CNVC_BYPASS_MSB_ALIGN, mask_sh), \
+ TF_SF(CNVC_CFG0_FORMAT_CONTROL, CLAMP_POSITIVE, mask_sh), \
+ TF_SF(CNVC_CFG0_FORMAT_CONTROL, CLAMP_POSITIVE_C, mask_sh), \
+ TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_R, mask_sh), \
+ TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_G, mask_sh), \
+ TF_SF(CNVC_CFG0_FORMAT_CONTROL, FORMAT_CROSSBAR_B, mask_sh), \
+ TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT0, mask_sh), \
+ TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT01, ALPHA_2BIT_LUT1, mask_sh), \
+ TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT2, mask_sh), \
+ TF_SF(CNVC_CFG0_ALPHA_2BIT_LUT23, ALPHA_2BIT_LUT3, mask_sh), \
+ TF_SF(CNVC_CFG0_FCNV_FP_BIAS_R, FCNV_FP_BIAS_R, mask_sh), \
+ TF_SF(CNVC_CFG0_FCNV_FP_BIAS_G, FCNV_FP_BIAS_G, mask_sh), \
+ TF_SF(CNVC_CFG0_FCNV_FP_BIAS_B, FCNV_FP_BIAS_B, mask_sh), \
+ TF_SF(CNVC_CFG0_FCNV_FP_SCALE_R, FCNV_FP_SCALE_R, mask_sh), \
+ TF_SF(CNVC_CFG0_FCNV_FP_SCALE_G, FCNV_FP_SCALE_G, mask_sh), \
+ TF_SF(CNVC_CFG0_FCNV_FP_SCALE_B, FCNV_FP_SCALE_B, mask_sh), \
+ TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, COLOR_KEYER_EN, mask_sh), \
+ TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, LUMA_KEYER_EN, mask_sh), \
+ TF_SF(CNVC_CFG0_COLOR_KEYER_CONTROL, COLOR_KEYER_MODE, mask_sh), \
+ TF_SF(CNVC_CFG0_COLOR_KEYER_ALPHA, COLOR_KEYER_ALPHA_LOW, mask_sh), \
+ TF_SF(CNVC_CFG0_COLOR_KEYER_ALPHA, COLOR_KEYER_ALPHA_HIGH, mask_sh), \
+ TF_SF(CNVC_CFG0_COLOR_KEYER_RED, COLOR_KEYER_RED_LOW, mask_sh), \
+ TF_SF(CNVC_CFG0_COLOR_KEYER_RED, COLOR_KEYER_RED_HIGH, mask_sh), \
+ TF_SF(CNVC_CFG0_COLOR_KEYER_GREEN, COLOR_KEYER_GREEN_LOW, mask_sh), \
+ TF_SF(CNVC_CFG0_COLOR_KEYER_GREEN, COLOR_KEYER_GREEN_HIGH, mask_sh), \
+ TF_SF(CNVC_CFG0_COLOR_KEYER_BLUE, COLOR_KEYER_BLUE_LOW, mask_sh), \
+ TF_SF(CNVC_CFG0_COLOR_KEYER_BLUE, COLOR_KEYER_BLUE_HIGH, mask_sh), \
+ TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_PIX_INV_MODE, mask_sh), \
+ TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_PIXEL_ALPHA_MOD_EN, mask_sh), \
+ TF_SF(CM_CUR0_CURSOR0_CONTROL, CUR0_ROM_EN, mask_sh),\
+ TF_SF(DSCL0_OBUF_MEM_PWR_CTRL, OBUF_MEM_PWR_FORCE, mask_sh),\
+ TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, mask_sh),\
+ TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_DIS, mask_sh),\
+ TF_SF(DSCL0_DSCL_MEM_PWR_STATUS, LUT_MEM_PWR_STATE, mask_sh),\
+ TF_SF(DSCL0_DSCL_SC_MODE, SCL_SC_MATRIX_MODE, mask_sh),\
+ TF_SF(DSCL0_DSCL_SC_MODE, SCL_SC_LTONL_EN, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_MODE, SCL_EASF_H_EN, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_MODE, SCL_EASF_H_RINGEST_FORCE_EN, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_MODE, SCL_EASF_H_2TAP_SHARP_FACTOR, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF1_EN, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_MODE, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF3_MODE, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_FLAT1_GAIN, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_FLAT2_GAIN, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF_CNTL, SCL_EASF_H_BF2_ROC_GAIN, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_REDUCE, SCL_EASF_H_RINGEST_EVENTAP_REDUCEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_REDUCE, SCL_EASF_H_RINGEST_EVENTAP_REDUCEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_GAIN, SCL_EASF_H_RINGEST_EVENTAP_GAIN1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_RINGEST_EVENTAP_GAIN, SCL_EASF_H_RINGEST_EVENTAP_GAIN2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MAXA, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MAXB, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MINA, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MINB, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG0, SCL_EASF_H_BF1_PWL_IN_SEG0, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG0, SCL_EASF_H_BF1_PWL_BASE_SEG0, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG0, SCL_EASF_H_BF1_PWL_SLOPE_SEG0, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG1, SCL_EASF_H_BF1_PWL_IN_SEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG1, SCL_EASF_H_BF1_PWL_BASE_SEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG1, SCL_EASF_H_BF1_PWL_SLOPE_SEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG2, SCL_EASF_H_BF1_PWL_IN_SEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG2, SCL_EASF_H_BF1_PWL_BASE_SEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG2, SCL_EASF_H_BF1_PWL_SLOPE_SEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG3, SCL_EASF_H_BF1_PWL_IN_SEG3, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG3, SCL_EASF_H_BF1_PWL_BASE_SEG3, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG3, SCL_EASF_H_BF1_PWL_SLOPE_SEG3, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG4, SCL_EASF_H_BF1_PWL_IN_SEG4, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG4, SCL_EASF_H_BF1_PWL_BASE_SEG4, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG4, SCL_EASF_H_BF1_PWL_SLOPE_SEG4, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG5, SCL_EASF_H_BF1_PWL_IN_SEG5, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG5, SCL_EASF_H_BF1_PWL_BASE_SEG5, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG5, SCL_EASF_H_BF1_PWL_SLOPE_SEG5, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG6, SCL_EASF_H_BF1_PWL_IN_SEG6, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG6, SCL_EASF_H_BF1_PWL_BASE_SEG6, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG6, SCL_EASF_H_BF1_PWL_SLOPE_SEG6, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG7, SCL_EASF_H_BF1_PWL_IN_SEG7, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF1_PWL_SEG7, SCL_EASF_H_BF1_PWL_BASE_SEG7, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG0, SCL_EASF_H_BF3_PWL_IN_SEG0, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG0, SCL_EASF_H_BF3_PWL_BASE_SEG0, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG0, SCL_EASF_H_BF3_PWL_SLOPE_SEG0, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG1, SCL_EASF_H_BF3_PWL_IN_SEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG1, SCL_EASF_H_BF3_PWL_BASE_SEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG1, SCL_EASF_H_BF3_PWL_SLOPE_SEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG2, SCL_EASF_H_BF3_PWL_IN_SEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG2, SCL_EASF_H_BF3_PWL_BASE_SEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG2, SCL_EASF_H_BF3_PWL_SLOPE_SEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG3, SCL_EASF_H_BF3_PWL_IN_SEG3, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG3, SCL_EASF_H_BF3_PWL_BASE_SEG3, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG3, SCL_EASF_H_BF3_PWL_SLOPE_SEG3, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG4, SCL_EASF_H_BF3_PWL_IN_SEG4, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG4, SCL_EASF_H_BF3_PWL_BASE_SEG4, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG4, SCL_EASF_H_BF3_PWL_SLOPE_SEG4, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG5, SCL_EASF_H_BF3_PWL_IN_SEG5, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_H_BF3_PWL_SEG5, SCL_EASF_H_BF3_PWL_BASE_SEG5, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_MODE, SCL_EASF_V_EN, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_MODE, SCL_EASF_V_RINGEST_FORCE_EN, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_MODE, SCL_EASF_V_2TAP_SHARP_FACTOR, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF1_EN, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_MODE, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF3_MODE, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_FLAT1_GAIN, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_FLAT2_GAIN, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF_CNTL, SCL_EASF_V_BF2_ROC_GAIN, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL1, SCL_EASF_V_RINGEST_3TAP_DNTILT_UPTILT, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL1, SCL_EASF_V_RINGEST_3TAP_UPTILT_MAXVAL, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL2, SCL_EASF_V_RINGEST_3TAP_DNTILT_SLOPE, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL2, SCL_EASF_V_RINGEST_3TAP_UPTILT1_SLOPE, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL3, SCL_EASF_V_RINGEST_3TAP_UPTILT2_SLOPE, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_RINGEST_3TAP_CNTL3, SCL_EASF_V_RINGEST_3TAP_UPTILT2_OFFSET, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_REDUCE, SCL_EASF_V_RINGEST_EVENTAP_REDUCEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_REDUCE, SCL_EASF_V_RINGEST_EVENTAP_REDUCEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_GAIN, SCL_EASF_V_RINGEST_EVENTAP_GAIN1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_RINGEST_EVENTAP_GAIN, SCL_EASF_V_RINGEST_EVENTAP_GAIN2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MAXA, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MAXB, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MINA, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MINB, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG0, SCL_EASF_V_BF1_PWL_IN_SEG0, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG0, SCL_EASF_V_BF1_PWL_BASE_SEG0, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG0, SCL_EASF_V_BF1_PWL_SLOPE_SEG0, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG1, SCL_EASF_V_BF1_PWL_IN_SEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG1, SCL_EASF_V_BF1_PWL_BASE_SEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG1, SCL_EASF_V_BF1_PWL_SLOPE_SEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG2, SCL_EASF_V_BF1_PWL_IN_SEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG2, SCL_EASF_V_BF1_PWL_BASE_SEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG2, SCL_EASF_V_BF1_PWL_SLOPE_SEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG3, SCL_EASF_V_BF1_PWL_IN_SEG3, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG3, SCL_EASF_V_BF1_PWL_BASE_SEG3, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG3, SCL_EASF_V_BF1_PWL_SLOPE_SEG3, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG4, SCL_EASF_V_BF1_PWL_IN_SEG4, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG4, SCL_EASF_V_BF1_PWL_BASE_SEG4, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG4, SCL_EASF_V_BF1_PWL_SLOPE_SEG4, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG5, SCL_EASF_V_BF1_PWL_IN_SEG5, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG5, SCL_EASF_V_BF1_PWL_BASE_SEG5, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG5, SCL_EASF_V_BF1_PWL_SLOPE_SEG5, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG6, SCL_EASF_V_BF1_PWL_IN_SEG6, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG6, SCL_EASF_V_BF1_PWL_BASE_SEG6, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG6, SCL_EASF_V_BF1_PWL_SLOPE_SEG6, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG7, SCL_EASF_V_BF1_PWL_IN_SEG7, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF1_PWL_SEG7, SCL_EASF_V_BF1_PWL_BASE_SEG7, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG0, SCL_EASF_V_BF3_PWL_IN_SEG0, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG0, SCL_EASF_V_BF3_PWL_BASE_SEG0, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG0, SCL_EASF_V_BF3_PWL_SLOPE_SEG0, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG1, SCL_EASF_V_BF3_PWL_IN_SEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG1, SCL_EASF_V_BF3_PWL_BASE_SEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG1, SCL_EASF_V_BF3_PWL_SLOPE_SEG1, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG2, SCL_EASF_V_BF3_PWL_IN_SEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG2, SCL_EASF_V_BF3_PWL_BASE_SEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG2, SCL_EASF_V_BF3_PWL_SLOPE_SEG2, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG3, SCL_EASF_V_BF3_PWL_IN_SEG3, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG3, SCL_EASF_V_BF3_PWL_BASE_SEG3, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG3, SCL_EASF_V_BF3_PWL_SLOPE_SEG3, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG4, SCL_EASF_V_BF3_PWL_IN_SEG4, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG4, SCL_EASF_V_BF3_PWL_BASE_SEG4, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG4, SCL_EASF_V_BF3_PWL_SLOPE_SEG4, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG5, SCL_EASF_V_BF3_PWL_IN_SEG5, mask_sh),\
+ TF_SF(DSCL0_DSCL_EASF_V_BF3_PWL_SEG5, SCL_EASF_V_BF3_PWL_BASE_SEG5, mask_sh),\
+ TF_SF(DSCL0_DSCL_SC_MATRIX_C0C1, SCL_SC_MATRIX_C0, mask_sh),\
+ TF_SF(DSCL0_DSCL_SC_MATRIX_C0C1, SCL_SC_MATRIX_C1, mask_sh),\
+ TF_SF(DSCL0_DSCL_SC_MATRIX_C2C3, SCL_SC_MATRIX_C2, mask_sh),\
+ TF_SF(DSCL0_DSCL_SC_MATRIX_C2C3, SCL_SC_MATRIX_C3, mask_sh),\
+ TF_SF(DSCL0_ISHARP_DELTA_CTRL, ISHARP_DELTA_LUT_HOST_SELECT, mask_sh),\
+ TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_DIS, mask_sh),\
+ TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_FORCE, mask_sh),\
+ TF_SF(DSCL0_ISHARP_DELTA_LUT_MEM_PWR_CTRL, ISHARP_DELTA_LUT_MEM_PWR_STATE, mask_sh),\
+ TF_SF(DSCL0_ISHARP_DELTA_DATA, ISHARP_DELTA_DATA, mask_sh),\
+ TF_SF(DSCL0_ISHARP_DELTA_INDEX, ISHARP_DELTA_INDEX, mask_sh),\
+ TF_SF(DSCL0_ISHARP_MODE, ISHARP_EN, mask_sh),\
+ TF_SF(DSCL0_ISHARP_MODE, ISHARP_NOISEDET_EN, mask_sh),\
+ TF_SF(DSCL0_ISHARP_MODE, ISHARP_NOISEDET_MODE, mask_sh),\
+ TF_SF(DSCL0_ISHARP_MODE, ISHARP_LBA_MODE, mask_sh),\
+ TF_SF(DSCL0_ISHARP_MODE, ISHARP_DELTA_LUT_SELECT, mask_sh),\
+ TF_SF(DSCL0_ISHARP_MODE, ISHARP_FMT_MODE, mask_sh),\
+ TF_SF(DSCL0_ISHARP_MODE, ISHARP_FMT_NORM, mask_sh),\
+ TF_SF(DSCL0_ISHARP_MODE, ISHARP_DELTA_LUT_SELECT_CURRENT, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG0, ISHARP_LBA_PWL_IN_SEG0, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG0, ISHARP_LBA_PWL_BASE_SEG0, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG0, ISHARP_LBA_PWL_SLOPE_SEG0, mask_sh), \
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG1, ISHARP_LBA_PWL_IN_SEG1, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG1, ISHARP_LBA_PWL_BASE_SEG1, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG1, ISHARP_LBA_PWL_SLOPE_SEG1, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG2, ISHARP_LBA_PWL_IN_SEG2, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG2, ISHARP_LBA_PWL_BASE_SEG2, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG2, ISHARP_LBA_PWL_SLOPE_SEG2, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG3, ISHARP_LBA_PWL_IN_SEG3, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG3, ISHARP_LBA_PWL_BASE_SEG3, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG3, ISHARP_LBA_PWL_SLOPE_SEG3, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG4, ISHARP_LBA_PWL_IN_SEG4, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG4, ISHARP_LBA_PWL_BASE_SEG4, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG4, ISHARP_LBA_PWL_SLOPE_SEG4, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG5, ISHARP_LBA_PWL_IN_SEG5, mask_sh),\
+ TF_SF(DSCL0_ISHARP_LBA_PWL_SEG5, ISHARP_LBA_PWL_BASE_SEG5, mask_sh),\
+ TF_SF(DSCL0_ISHARP_NOISEDET_THRESHOLD, ISHARP_NOISEDET_UTHRE, mask_sh),\
+ TF_SF(DSCL0_ISHARP_NOISEDET_THRESHOLD, ISHARP_NOISEDET_DTHRE, mask_sh), \
+ TF_SF(DSCL0_ISHARP_NOISE_GAIN_PWL, ISHARP_NOISEDET_PWL_START_IN, mask_sh), \
+ TF_SF(DSCL0_ISHARP_NOISE_GAIN_PWL, ISHARP_NOISEDET_PWL_END_IN, mask_sh), \
+ TF_SF(DSCL0_ISHARP_NOISE_GAIN_PWL, ISHARP_NOISEDET_PWL_SLOPE, mask_sh), \
+ TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_EN_P, mask_sh), \
+ TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_PIVOT_P, mask_sh), \
+ TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_SLOPE_P, mask_sh), \
+ TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_EN_N, mask_sh), \
+ TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_PIVOT_N, mask_sh), \
+ TF_SF(DSCL0_ISHARP_NLDELTA_SOFT_CLIP, ISHARP_NLDELTA_SCLIP_SLOPE_N, mask_sh), \
+ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_FRAC_BOT, mask_sh),\
+ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT, SCL_V_INIT_INT_BOT, mask_sh),\
+ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_FRAC_BOT_C, mask_sh),\
+ TF_SF(DSCL0_SCL_VERT_FILTER_INIT_BOT_C, SCL_V_INIT_INT_BOT_C, mask_sh)
+
+#define DPP_REG_FIELD_LIST_DCN42(type) \
+ DPP_REG_FIELD_LIST_DCN401(type); \
+ type CM_HIST_SEL; \
+ type CM_HIST_CH_EN; \
+ type CM_HIST_SRC1_SEL; \
+ type CM_HIST_SRC2_SEL; \
+ type CM_HIST_SRC3_SEL; \
+ type CM_HIST_CH1_XBAR; \
+ type CM_HIST_CH2_XBAR; \
+ type CM_HIST_CH3_XBAR; \
+ type CM_HIST_FORMAT; \
+ type CM_HIST_READ_CHANNEL_MASK; \
+ type CM_HIST_LOCK; \
+ type CM_HIST_INDEX; \
+ type CM_HIST_DATA; \
+ type CM_HIST_BUFA_RDY_STATUS; \
+ type CM_HIST_BUFB_RDY_STATUS; \
+ type CM_HIST_SCALE_SRC1; \
+ type CM_HIST_COEFA_SRC2; \
+ type CM_HIST_COEFB_SRC2; \
+ type CM_HIST_COEFC_SRC2; \
+ type CM_HIST_SCALE_SRC3; \
+ type CM_HIST_BIAS_SRC1; \
+ type CM_HIST_BIAS_SRC2; \
+ type CM_HIST_BIAS_SRC3
+
+
+#define DPP_REG_VARIABLE_LIST_DCN42 \
+ DPP_REG_VARIABLE_LIST_DCN401; \
+ uint32_t ALPHA_2BIT_LUT01; \
+ uint32_t ALPHA_2BIT_LUT23; \
+ uint32_t CM_HIST_CNTL; \
+ uint32_t CM_HIST_INDEX; \
+ uint32_t CM_HIST_LOCK; \
+ uint32_t CM_HIST_DATA; \
+ uint32_t CM_HIST_STATUS; \
+ uint32_t CM_HIST_SCALE_SRC1; \
+ uint32_t CM_HIST_COEFA_SRC2; \
+ uint32_t CM_HIST_COEFB_SRC2; \
+ uint32_t CM_HIST_COEFC_SRC2; \
+ uint32_t CM_HIST_SCALE_SRC3; \
+ uint32_t CM_HIST_BIAS_SRC1; \
+ uint32_t CM_HIST_BIAS_SRC2; \
+ uint32_t CM_HIST_BIAS_SRC3
+
+struct dcn42_dpp_registers {
+ DPP_REG_VARIABLE_LIST_DCN42;
+};
+
+struct dcn42_dpp_shift {
+ DPP_REG_FIELD_LIST_DCN42(uint8_t);
+};
+
+struct dcn42_dpp_mask {
+ DPP_REG_FIELD_LIST_DCN42(uint32_t);
+};
+struct dcn42_dpp {
+ struct dpp base;
+ const struct dcn42_dpp_registers *tf_regs;
+ const struct dcn42_dpp_shift *tf_shift;
+ const struct dcn42_dpp_mask *tf_mask;
+ const uint16_t *filter_v;
+ const uint16_t *filter_h;
+ const uint16_t *filter_v_c;
+ const uint16_t *filter_h_c;
+ int lb_pixel_depth_supported;
+ int lb_memory_size;
+ int lb_bits_per_entry;
+ bool is_write_to_ram_a_safe;
+ struct scaler_data scl_data;
+ struct pwl_params pwl_data;
+};
+
+bool dpp42_construct(struct dcn42_dpp *dpp42,
+ struct dc_context *ctx,
+ uint32_t inst,
+ const struct dcn42_dpp_registers *tf_regs,
+ const struct dcn42_dpp_shift *tf_shift,
+ const struct dcn42_dpp_mask *tf_mask);
+
+
+#endif /* __DCN42_DPP_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c
index c1bdbb38c690..3bf737195bac 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c
@@ -107,6 +107,11 @@ void dsc401_read_state(struct display_stream_compressor *dsc, struct dcn_dsc_sta
REG_GET(DSCC_PPS_CONFIG7, SLICE_BPG_OFFSET, &s->dsc_slice_bpg_offset);
REG_GET_2(DSCRM_DSC_FORWARD_CONFIG, DSCRM_DSC_FORWARD_EN, &s->dsc_fw_en,
DSCRM_DSC_OPP_PIPE_SOURCE, &s->dsc_opp_source);
+ REG_GET(DSCC_PPS_CONFIG1, BLOCK_PRED_ENABLE, &s->dsc_block_pred_enable);
+ REG_GET(DSCC_PPS_CONFIG0, LINEBUF_DEPTH, &s->dsc_line_buf_depth);
+ REG_GET(DSCC_PPS_CONFIG0, DSC_VERSION_MINOR, &s->dsc_version_minor);
+ REG_GET(DSCC_CONFIG1, DSCC_RATE_CONTROL_BUFFER_MODEL_SIZE, &s->dsc_rc_buffer_size);
+ REG_GET(DSCC_PPS_CONFIG0, SIMPLE_422, &s->dsc_simple_422);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dsc.h b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h
index ad7ef83694ea..a16c60d8532f 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dsc.h
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dsc.h
@@ -64,6 +64,11 @@ struct dcn_dsc_state {
uint32_t dsc_chunk_size;
uint32_t dsc_fw_en;
uint32_t dsc_opp_source;
+ uint32_t dsc_block_pred_enable;
+ uint32_t dsc_line_buf_depth;
+ uint32_t dsc_version_minor;
+ uint32_t dsc_rc_buffer_size;
+ uint32_t dsc_simple_422;
};
struct dcn_dsc_reg_state {
diff --git a/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c b/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c
index bc058f682438..0ee4f83a02eb 100644
--- a/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c
+++ b/drivers/gpu/drm/amd/display/dc/dwb/dcn30/dcn30_dwb.c
@@ -45,6 +45,7 @@
static bool dwb3_get_caps(struct dwbc *dwbc, struct dwb_caps *caps)
{
+ (void)dwbc;
if (caps) {
caps->adapter_id = 0; /* we only support 1 adapter currently */
caps->hw_version = DCN_VERSION_3_0;
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile
index b72e2a9f9a28..f8142ebf363f 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright 2017 Advanced Micro Devices, Inc.
+# Copyright 2017-2026 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -132,3 +132,14 @@ AMD_DAL_GPIO_DCN401 = $(addprefix $(AMDDALPATH)/dc/gpio/dcn401/,$(GPIO_DCN401))
AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCN401)
+###############################################################################
+# DCN 4.2
+###############################################################################
+
+GPIO_DCN42 = hw_translate_dcn42.o hw_factory_dcn42.o
+
+AMD_DAL_GPIO_DCN42 = $(addprefix $(AMDDALPATH)/dc/gpio/dcn42/,$(GPIO_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCN42)
+
+
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.c
new file mode 100644
index 000000000000..7d2090c7870e
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.c
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+#include "../hw_factory.h"
+
+
+#include "../hw_gpio.h"
+#include "../hw_ddc.h"
+#include "../hw_hpd.h"
+#include "../hw_generic.h"
+
+
+
+#include "dcn/dcn_4_2_0_offset.h"
+#include "dcn/dcn_4_2_0_sh_mask.h"
+#include "dpcs/dpcs_4_0_0_offset.h"
+#include "dpcs/dpcs_4_0_0_sh_mask.h"
+
+#include "reg_helper.h"
+#include "../hpd_regs.h"
+#include "hw_factory_dcn42.h"
+
+#define DCN_BASE__INST0_SEG2 0x000034C0
+
+/* begin *********************
+ * macros to expend register list macro defined in HW object header file */
+
+/* DCN */
+#define block HPD
+#define reg_num 0
+
+#undef BASE_INNER
+#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
+
+#define BASE(seg) BASE_INNER(seg)
+
+
+
+#define REG(reg_name)\
+ (BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name)
+
+#define SF_HPD(reg_name, field_name, post_fix)\
+ .field_name = HPD0_ ## reg_name ## __ ## field_name ## post_fix
+
+#define REGI(reg_name, block, id)\
+ (BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
+ reg ## block ## id ## _ ## reg_name)
+
+#define SF(reg_name, field_name, post_fix)\
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
+/* macros to expend register list macro defined in HW object header file
+ * end *********************/
+
+// DC_GPIO_HPD_* registers are gone.
+#undef HPD_REG_LIST
+#define HPD_REG_LIST(id) \
+ .int_status = REGI(DC_HPD_INT_STATUS, HPD, id),\
+ .toggle_filt_cntl = REGI(DC_HPD_TOGGLE_FILT_CNTL, HPD, id)
+
+#define hpd_regs(id) \
+{\
+ HPD_REG_LIST(id)\
+}
+
+static const struct hpd_registers hpd_regs[] = {
+ hpd_regs(0),
+ hpd_regs(1),
+ hpd_regs(2),
+ hpd_regs(3),
+ hpd_regs(4),
+};
+
+static const struct hpd_sh_mask hpd_shift = {
+ HPD_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct hpd_sh_mask hpd_mask = {
+ HPD_MASK_SH_LIST(_MASK)
+};
+
+#include "../ddc_regs.h"
+
+ /* set field name */
+#define SF_DDC(reg_name, field_name, post_fix)\
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
+static const struct ddc_registers ddc_data_regs_dcn[] = {
+ ddc_data_regs_dcn2(1),
+ ddc_data_regs_dcn2(2),
+ ddc_data_regs_dcn2(3),
+ ddc_data_regs_dcn2(4),
+ ddc_data_regs_dcn2(5),
+ {
+ // add a dummy entry for cases no such port
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ .ddc_setup = 0,
+ .phy_aux_cntl = 0,
+ .dc_gpio_aux_ctrl_5 = 0
+ },
+ {
+ DDC_GPIO_VGA_REG_LIST(DATA),
+ .ddc_setup = 0,
+ .phy_aux_cntl = 0,
+ .dc_gpio_aux_ctrl_5 = 0
+ }
+};
+
+static const struct ddc_registers ddc_clk_regs_dcn[] = {
+ ddc_clk_regs_dcn2(1),
+ ddc_clk_regs_dcn2(2),
+ ddc_clk_regs_dcn2(3),
+ ddc_clk_regs_dcn2(4),
+ ddc_clk_regs_dcn2(5),
+ {
+ // add a dummy entry for cases no such port
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+ .ddc_setup = 0,
+ .phy_aux_cntl = 0,
+ .dc_gpio_aux_ctrl_5 = 0
+ },
+ {
+ DDC_GPIO_VGA_REG_LIST(CLK),
+ .ddc_setup = 0,
+ .phy_aux_cntl = 0,
+ .dc_gpio_aux_ctrl_5 = 0
+ }
+};
+
+static const struct ddc_sh_mask ddc_shift[] = {
+ DDC_MASK_SH_LIST_DCN2(__SHIFT, 1),
+ DDC_MASK_SH_LIST_DCN2(__SHIFT, 2),
+ DDC_MASK_SH_LIST_DCN2(__SHIFT, 3),
+ DDC_MASK_SH_LIST_DCN2(__SHIFT, 4),
+ DDC_MASK_SH_LIST_DCN2(__SHIFT, 5),
+ DDC_MASK_SH_LIST_DCN2(__SHIFT, 6),
+ DDC_MASK_SH_LIST_DCN2_VGA(__SHIFT)
+};
+
+static const struct ddc_sh_mask ddc_mask[] = {
+ DDC_MASK_SH_LIST_DCN2(_MASK, 1),
+ DDC_MASK_SH_LIST_DCN2(_MASK, 2),
+ DDC_MASK_SH_LIST_DCN2(_MASK, 3),
+ DDC_MASK_SH_LIST_DCN2(_MASK, 4),
+ DDC_MASK_SH_LIST_DCN2(_MASK, 5),
+ DDC_MASK_SH_LIST_DCN2(_MASK, 6),
+ DDC_MASK_SH_LIST_DCN2_VGA(_MASK)
+};
+
+#include "../generic_regs.h"
+
+/* set field name */
+#define SF_GENERIC(reg_name, field_name, post_fix)\
+ .field_name = 0
+
+static const struct generic_registers generic_regs[] = {
+ {{ 0 }},
+ {{ 0 }},
+};
+
+static const struct generic_sh_mask generic_shift[] = {
+ { 0 },
+ { 0 },
+};
+
+static const struct generic_sh_mask generic_mask[] = {
+ { 0 },
+ { 0 },
+};
+
+static void define_generic_registers(struct hw_gpio_pin *pin, uint32_t en)
+{
+ struct hw_generic *generic = HW_GENERIC_FROM_BASE(pin);
+
+ generic->regs = &generic_regs[en];
+ generic->shifts = &generic_shift[en];
+ generic->masks = &generic_mask[en];
+ generic->base.regs = &generic_regs[en].gpio;
+}
+
+static void define_ddc_registers(
+ struct hw_gpio_pin *pin,
+ uint32_t en)
+{
+ struct hw_ddc *ddc = HW_DDC_FROM_BASE(pin);
+
+ switch (pin->id) {
+ case GPIO_ID_DDC_DATA:
+ ddc->regs = &ddc_data_regs_dcn[en];
+ ddc->base.regs = &ddc_data_regs_dcn[en].gpio;
+ break;
+ case GPIO_ID_DDC_CLOCK:
+ ddc->regs = &ddc_clk_regs_dcn[en];
+ ddc->base.regs = &ddc_clk_regs_dcn[en].gpio;
+ break;
+ default:
+ ASSERT_CRITICAL(false);
+ return;
+ }
+
+ ddc->shifts = &ddc_shift[en];
+ ddc->masks = &ddc_mask[en];
+
+}
+
+static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en)
+{
+ struct hw_hpd *hpd = HW_HPD_FROM_BASE(pin);
+
+ hpd->regs = &hpd_regs[en];
+ hpd->shifts = &hpd_shift;
+ hpd->masks = &hpd_mask;
+ hpd->base.regs = &hpd_regs[en].gpio;
+}
+
+
+/* function table */
+static const struct hw_factory_funcs funcs = {
+ .init_ddc_data = dal_hw_ddc_init,
+ .init_generic = dal_hw_generic_init,
+ .init_hpd = dal_hw_hpd_init,
+ .get_ddc_pin = dal_hw_ddc_get_pin,
+ .get_hpd_pin = dal_hw_hpd_get_pin,
+ .get_generic_pin = dal_hw_generic_get_pin,
+ .define_hpd_registers = define_hpd_registers,
+ .define_ddc_registers = define_ddc_registers,
+ .define_generic_registers = define_generic_registers
+};
+
+/*
+ * dal_hw_factory_dcn42_init
+ *
+ * @brief
+ * Initialize HW factory function pointers and pin info
+ *
+ * @param
+ * struct hw_factory *factory - [out] struct of function pointers
+ */
+void dal_hw_factory_dcn42_init(struct hw_factory *factory)
+{
+ factory->number_of_pins[GPIO_ID_DDC_DATA] = 8;
+ factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8;
+ factory->number_of_pins[GPIO_ID_GENERIC] = 4;
+ factory->number_of_pins[GPIO_ID_HPD] = 5;
+ factory->number_of_pins[GPIO_ID_GPIO_PAD] = 28;
+ factory->number_of_pins[GPIO_ID_VIP_PAD] = 0;
+ factory->number_of_pins[GPIO_ID_SYNC] = 0;
+ factory->number_of_pins[GPIO_ID_GSL] = 0;/*add this*/
+
+ factory->funcs = &funcs;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.h b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.h
new file mode 100644
index 000000000000..b723380eb17f
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_factory_dcn42.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __DAL_HW_FACTORY_DCN42_H__
+#define __DAL_HW_FACTORY_DCN42_H__
+
+/* Initialize HW factory function pointers and pin info */
+void dal_hw_factory_dcn42_init(struct hw_factory *factory);
+
+#endif /* __DAL_HW_FACTORY_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c
new file mode 100644
index 000000000000..e7e1d9979876
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.c
@@ -0,0 +1,206 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "hw_translate_dcn42.h"
+
+#include "dm_services.h"
+#include "include/gpio_types.h"
+#include "../hw_translate.h"
+
+
+#include "dcn/dcn_4_2_0_offset.h"
+#include "dcn/dcn_4_2_0_sh_mask.h"
+#include "dpcs/dpcs_4_0_0_offset.h"
+#include "dpcs/dpcs_4_0_0_sh_mask.h"
+
+#define DCN_BASE__INST0_SEG2 0x000034C0
+
+/* begin *********************
+ * macros to expend register list macro defined in HW object header file */
+
+/* DCN */
+#define block HPD
+#define reg_num 0
+
+#undef BASE_INNER
+#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
+
+#define BASE(seg) BASE_INNER(seg)
+
+#undef REG
+#define REG(reg_name)\
+ (BASE(reg ## reg_name ## _BASE_IDX) + reg ## reg_name)
+#define SF_HPD(reg_name, field_name, post_fix)\
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
+
+/* macros to expend register list macro defined in HW object header file
+ * end *********************/
+
+
+static bool offset_to_id(
+ uint32_t offset,
+ uint32_t mask,
+ enum gpio_id *id,
+ uint32_t *en)
+{
+ (void)mask;
+ switch (offset) {
+ /* HPD */
+ case REG(HPD0_DC_HPD_INT_STATUS):
+ *id = GPIO_ID_HPD;
+ *en = GPIO_HPD_1;
+ return true;
+ case REG(HPD1_DC_HPD_INT_STATUS):
+ *id = GPIO_ID_HPD;
+ *en = GPIO_HPD_2;
+ return true;
+ case REG(HPD2_DC_HPD_INT_STATUS):
+ *id = GPIO_ID_HPD;
+ *en = GPIO_HPD_3;
+ return true;
+ case REG(HPD3_DC_HPD_INT_STATUS):
+ *id = GPIO_ID_HPD;
+ *en = GPIO_HPD_4;
+ return true;
+ case REG(HPD4_DC_HPD_INT_STATUS):
+ *id = GPIO_ID_HPD;
+ *en = GPIO_HPD_5;
+ return true;
+ /* DDC */
+ /* we don't care about the GPIO_ID for DDC
+ * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK
+ * directly in the create method
+ */
+ case REG(DC_GPIO_DDC1_A):
+ *en = GPIO_DDC_LINE_DDC1;
+ return true;
+ case REG(DC_GPIO_DDC2_A):
+ *en = GPIO_DDC_LINE_DDC2;
+ return true;
+ case REG(DC_GPIO_DDC3_A):
+ *en = GPIO_DDC_LINE_DDC3;
+ return true;
+ case REG(DC_GPIO_DDC4_A):
+ *en = GPIO_DDC_LINE_DDC4;
+ return true;
+ case REG(DC_GPIO_DDC5_A):
+ *en = GPIO_DDC_LINE_DDC5;
+ return true;
+ case REG(DC_GPIO_DDCVGA_A):
+ *en = GPIO_DDC_LINE_DDC_VGA;
+ return true;
+ default:
+ ASSERT_CRITICAL(false);
+ return false;
+ }
+}
+
+
+static bool id_to_offset(
+ enum gpio_id id,
+ uint32_t en,
+ struct gpio_pin_info *info)
+{
+ bool result = true;
+
+ switch (id) {
+ case GPIO_ID_DDC_DATA:
+ info->mask = DC_GPIO_DDC1_A__DC_GPIO_DDC1DATA_A_MASK;
+ switch (en) {
+ case GPIO_DDC_LINE_DDC1:
+ info->offset = REG(DC_GPIO_DDC1_A);
+ break;
+ case GPIO_DDC_LINE_DDC2:
+ info->offset = REG(DC_GPIO_DDC2_A);
+ break;
+ case GPIO_DDC_LINE_DDC3:
+ info->offset = REG(DC_GPIO_DDC3_A);
+ break;
+ case GPIO_DDC_LINE_DDC4:
+ info->offset = REG(DC_GPIO_DDC4_A);
+ break;
+ case GPIO_DDC_LINE_DDC5:
+ info->offset = REG(DC_GPIO_DDC5_A);
+ break;
+ case GPIO_DDC_LINE_DDC_VGA:
+ info->offset = REG(DC_GPIO_DDCVGA_A);
+ break;
+ case GPIO_DDC_LINE_I2C_PAD:
+ default:
+ ASSERT_CRITICAL(false);
+ result = false;
+ }
+ break;
+ case GPIO_ID_DDC_CLOCK:
+ info->mask = DC_GPIO_DDC1_A__DC_GPIO_DDC1CLK_A_MASK;
+ switch (en) {
+ case GPIO_DDC_LINE_DDC1:
+ info->offset = REG(DC_GPIO_DDC1_A);
+ break;
+ case GPIO_DDC_LINE_DDC2:
+ info->offset = REG(DC_GPIO_DDC2_A);
+ break;
+ case GPIO_DDC_LINE_DDC3:
+ info->offset = REG(DC_GPIO_DDC3_A);
+ break;
+ case GPIO_DDC_LINE_DDC4:
+ info->offset = REG(DC_GPIO_DDC4_A);
+ break;
+ case GPIO_DDC_LINE_DDC5:
+ info->offset = REG(DC_GPIO_DDC5_A);
+ break;
+ case GPIO_DDC_LINE_DDC_VGA:
+ info->offset = REG(DC_GPIO_DDCVGA_A);
+ break;
+ case GPIO_DDC_LINE_I2C_PAD:
+ default:
+ ASSERT_CRITICAL(false);
+ result = false;
+ }
+ break;
+ case GPIO_ID_SYNC:
+ case GPIO_ID_VIP_PAD:
+ default:
+ ASSERT_CRITICAL(false);
+ result = false;
+ }
+
+ if (result) {
+ info->offset_y = info->offset + 2;
+ info->offset_en = info->offset + 1;
+ info->offset_mask = info->offset - 1;
+
+ info->mask_y = info->mask;
+ info->mask_en = info->mask;
+ info->mask_mask = info->mask;
+ }
+
+ return result;
+}
+
+
+/* function table */
+static const struct hw_translate_funcs funcs = {
+ .offset_to_id = offset_to_id,
+ .id_to_offset = id_to_offset,
+};
+
+
+/*
+ * dal_hw_translate_dcn42_init
+ *
+ * @brief
+ * Initialize Hw translate function pointers.
+ *
+ * @param
+ * struct hw_translate *tr - [out] struct of function pointers
+ *
+ */
+void dal_hw_translate_dcn42_init(struct hw_translate *tr)
+{
+ tr->funcs = &funcs;
+}
+
+
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.h b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.h
new file mode 100644
index 000000000000..007b4d55fef1
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn42/hw_translate_dcn42.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __DAL_HW_TRANSLATE_DCN42_H__
+#define __DAL_HW_TRANSLATE_DCN42_H__
+
+struct hw_translate;
+
+/* Initialize Hw translate function pointers */
+void dal_hw_translate_dcn42_init(struct hw_translate *tr);
+#ifdef DAL_EMULATION_SUPPORTED
+void dal_emulated_hw_translate_dcn42_init(struct hw_translate *tr);
+#endif
+
+#endif /* __DAL_HW_TRANSLATE_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
index 8bc67ca42197..d81a71ac00d2 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c
@@ -53,12 +53,14 @@
#include "dcn315/hw_factory_dcn315.h"
#include "dcn32/hw_factory_dcn32.h"
#include "dcn401/hw_factory_dcn401.h"
+#include "dcn42/hw_factory_dcn42.h"
bool dal_hw_factory_init(
struct hw_factory *factory,
enum dce_version dce_version,
enum dce_environment dce_environment)
{
+ (void)dce_environment;
switch (dce_version) {
#if defined(CONFIG_DRM_AMD_DC_SI)
case DCE_VERSION_6_0:
@@ -118,6 +120,9 @@ bool dal_hw_factory_init(
case DCN_VERSION_4_01:
dal_hw_factory_dcn401_init(factory);
return true;
+ case DCN_VERSION_4_2:
+ dal_hw_factory_dcn42_init(factory);
+ return true;
default:
ASSERT_CRITICAL(false);
return false;
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c
index 660510842ecf..f0d400972897 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_gpio.c
@@ -199,5 +199,6 @@ void dal_hw_gpio_construct(
void dal_hw_gpio_destruct(
struct hw_gpio *pin)
{
+ (void)pin;
ASSERT(!pin->base.opened);
}
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 cb79a2832287..e6e36a912b13 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c
@@ -53,6 +53,7 @@
#include "dcn315/hw_translate_dcn315.h"
#include "dcn32/hw_translate_dcn32.h"
#include "dcn401/hw_translate_dcn401.h"
+#include "dcn42/hw_translate_dcn42.h"
/*
* This unit
@@ -63,6 +64,7 @@ bool dal_hw_translate_init(
enum dce_version dce_version,
enum dce_environment dce_environment)
{
+ (void)dce_environment;
switch (dce_version) {
#if defined(CONFIG_DRM_AMD_DC_SI)
case DCE_VERSION_6_0:
@@ -119,6 +121,9 @@ bool dal_hw_translate_init(
case DCN_VERSION_4_01:
dal_hw_translate_dcn401_init(translate);
return true;
+ case DCN_VERSION_4_2:
+ dal_hw_translate_dcn42_init(translate);
+ return true;
default:
BREAK_TO_DEBUGGER();
return false;
diff --git a/drivers/gpu/drm/amd/display/dc/hpo/Makefile b/drivers/gpu/drm/amd/display/dc/hpo/Makefile
index 7f2c9ee0dff1..25b196714bd8 100644
--- a/drivers/gpu/drm/amd/display/dc/hpo/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/hpo/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright 2020 Advanced Micro Devices, Inc.
+# Copyright 2020-2026 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -47,4 +47,13 @@ HPO_DCN32 = dcn32_hpo_dp_link_encoder.o
AMD_DAL_HPO_DCN32 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn32/,$(HPO_DCN32))
AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN32)
+
+###############################################################################
+# DCN42
+###############################################################################
+HPO_DCN42 = dcn42_hpo_dp_link_encoder.o
+
+AMD_DAL_HPO_DCN42 = $(addprefix $(AMDDALPATH)/dc/hpo/dcn42/,$(HPO_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_HPO_DCN42)
endif
diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c
index 759b453385c4..92ed130aeaec 100644
--- a/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn31/dcn31_hpo_dp_stream_encoder.c
@@ -640,6 +640,11 @@ static void dcn31_hpo_dp_stream_enc_audio_setup(
REG_UPDATE(DP_STREAM_ENC_AUDIO_CONTROL,
DP_STREAM_ENC_INPUT_MUX_AUDIO_STREAM_SOURCE_SEL, az_inst);
+ if (enc3->hpo_se_mask->DP_STREAM_ENC_APG_CLOCK_EN) {
+ /*enable apg clk*/
+ REG_UPDATE(DP_STREAM_ENC_AUDIO_CONTROL,
+ DP_STREAM_ENC_APG_CLOCK_EN, 1);
+ }
ASSERT(enc->apg);
enc->apg->funcs->se_audio_setup(enc->apg, az_inst, info);
}
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 82c3b3ac1f0d..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
@@ -1,5 +1,5 @@
/*
- * Copyright 2019 Advanced Micro Devices, Inc.
+ * Copyright 2019-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -208,17 +208,24 @@
type CRC_CONT_MODE_ENABLE;\
type HBLANK_MINIMUM_SYMBOL_WIDTH
+#define DCN4_2_HPO_DP_STREAM_ENC_REG_FIELD_LIST(type) \
+ type DP_STREAM_ENC_APG_CLOCK_EN
+#define DCN4_2_HPO_DP_STREAM_ENC_MASK_SH_LIST(mask_sh)\
+ DCN3_1_HPO_DP_STREAM_ENC_MASK_SH_LIST(mask_sh),\
+ SE_SF(DP_STREAM_ENC0_DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC_APG_CLOCK_EN, mask_sh)
struct dcn31_hpo_dp_stream_encoder_registers {
DCN3_1_HPO_DP_STREAM_ENC_REGS;
};
struct dcn31_hpo_dp_stream_encoder_shift {
DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint8_t);
+ DCN4_2_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint8_t);
};
struct dcn31_hpo_dp_stream_encoder_mask {
DCN3_1_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint32_t);
+ DCN4_2_HPO_DP_STREAM_ENC_REG_FIELD_LIST(uint32_t);
};
struct dcn31_hpo_dp_stream_encoder {
@@ -241,5 +248,4 @@ void dcn31_hpo_dp_stream_encoder_construct(
const struct dcn31_hpo_dp_stream_encoder_shift *hpo_se_shift,
const struct dcn31_hpo_dp_stream_encoder_mask *hpo_se_mask);
-
#endif // __DAL_DCN31_HPO_STREAM_ENCODER_H__
diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.c b/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.c
new file mode 100644
index 000000000000..4b86b1bf6503
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dc_bios_types.h"
+#include "dcn31/dcn31_hpo_dp_link_encoder.h"
+#include "dcn32/dcn32_hpo_dp_link_encoder.h"
+#include "dcn42_hpo_dp_link_encoder.h"
+#include "reg_helper.h"
+#include "stream_encoder.h"
+
+#define DC_LOGGER \
+ enc3->base.ctx->logger
+
+#define REG(reg)\
+ (enc3->regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+ enc3->hpo_le_shift->field_name, enc3->hpo_le_mask->field_name
+
+
+#define CTX \
+ enc3->base.ctx
+
+
+static void dcn42_hpo_dp_link_enc_read_state(
+ struct hpo_dp_link_encoder *enc,
+ struct hpo_dp_link_enc_state *state)
+{
+ struct dcn31_hpo_dp_link_encoder *enc3 = DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(enc);
+
+ ASSERT(state);
+
+ REG_GET(DP_DPHY_SYM32_STATUS,
+ STATUS, &state->link_enc_enabled);
+ REG_GET(DP_DPHY_SYM32_CONTROL,
+ NUM_LANES, &state->lane_count);
+ REG_GET(DP_DPHY_SYM32_CONTROL,
+ MODE, (uint32_t *)&state->link_mode);
+
+ REG_GET_2(DP_DPHY_SYM32_SAT_VC0,
+ SAT_STREAM_SOURCE, &state->stream_src[0],
+ SAT_SLOT_COUNT, &state->slot_count[0]);
+ REG_GET_2(DP_DPHY_SYM32_SAT_VC1,
+ SAT_STREAM_SOURCE, &state->stream_src[1],
+ SAT_SLOT_COUNT, &state->slot_count[1]);
+ REG_GET_2(DP_DPHY_SYM32_SAT_VC2,
+ SAT_STREAM_SOURCE, &state->stream_src[2],
+ SAT_SLOT_COUNT, &state->slot_count[2]);
+
+ REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL0,
+ STREAM_VC_RATE_X, &state->vc_rate_x[0],
+ STREAM_VC_RATE_Y, &state->vc_rate_y[0]);
+ REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL1,
+ STREAM_VC_RATE_X, &state->vc_rate_x[1],
+ STREAM_VC_RATE_Y, &state->vc_rate_y[1]);
+ REG_GET_2(DP_DPHY_SYM32_VC_RATE_CNTL2,
+ STREAM_VC_RATE_X, &state->vc_rate_x[2],
+ STREAM_VC_RATE_Y, &state->vc_rate_y[2]);
+}
+
+static struct hpo_dp_link_encoder_funcs dcn42_hpo_dp_link_encoder_funcs = {
+ .enable_link_phy = dcn31_hpo_dp_link_enc_enable_dp_output,
+ .disable_link_phy = dcn31_hpo_dp_link_enc_disable_output,
+ .link_enable = dcn31_hpo_dp_link_enc_enable,
+ .link_disable = dcn31_hpo_dp_link_enc_disable,
+ .set_link_test_pattern = dcn31_hpo_dp_link_enc_set_link_test_pattern,
+ .update_stream_allocation_table = dcn31_hpo_dp_link_enc_update_stream_allocation_table,
+ .set_throttled_vcp_size = dcn31_hpo_dp_link_enc_set_throttled_vcp_size,
+ .is_in_alt_mode = dcn32_hpo_dp_link_enc_is_in_alt_mode,
+ .read_state = dcn42_hpo_dp_link_enc_read_state,
+ .set_ffe = dcn31_hpo_dp_link_enc_set_ffe,
+};
+
+void hpo_dp_link_encoder42_construct(struct dcn31_hpo_dp_link_encoder *enc31,
+ struct dc_context *ctx,
+ uint32_t inst,
+ const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs,
+ const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift,
+ const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask)
+{
+ enc31->base.ctx = ctx;
+
+ enc31->base.inst = inst;
+ enc31->base.funcs = &dcn42_hpo_dp_link_encoder_funcs;
+ enc31->base.hpd_source = HPD_SOURCEID_UNKNOWN;
+ enc31->base.transmitter = TRANSMITTER_UNKNOWN;
+
+ enc31->regs = hpo_le_regs;
+ enc31->hpo_le_shift = hpo_le_shift;
+ enc31->hpo_le_mask = hpo_le_mask;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.h b/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.h
new file mode 100644
index 000000000000..3e84d016507c
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/hpo/dcn42/dcn42_hpo_dp_link_encoder.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2026 Advanced Micro Devices, Inc. */
+
+
+#ifndef __DAL_DCN42_HPO_DP_LINK_ENCODER_H__
+#define __DAL_DCN42_HPO_DP_LINK_ENCODER_H__
+
+#include "link_encoder.h"
+
+void hpo_dp_link_encoder42_construct(struct dcn31_hpo_dp_link_encoder *enc31,
+ struct dc_context *ctx,
+ uint32_t inst,
+ const struct dcn31_hpo_dp_link_encoder_registers *hpo_le_regs,
+ const struct dcn31_hpo_dp_link_encoder_shift *hpo_le_shift,
+ const struct dcn31_hpo_dp_link_encoder_mask *hpo_le_mask);
+
+#endif // __DAL_DCN32_HPO_DP_LINK_ENCODER_H__
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/Makefile b/drivers/gpu/drm/amd/display/dc/hubbub/Makefile
index 66ca5a6a0415..29c8e2651442 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/Makefile
@@ -1,5 +1,5 @@
-# Copyright 2022 Advanced Micro Devices, Inc.
+# Copyright 2022-2026 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -101,4 +101,12 @@ AMD_DAL_HUBBUB_DCN401 = $(addprefix $(AMDDALPATH)/dc/hubbub/dcn401/,$(HUBBUB_DCN
AMD_DISPLAY_FILES += $(AMD_DAL_HUBBUB_DCN401)
###############################################################################
+# DCN42
+###############################################################################
+HUBBUB_DCN42 = dcn42_hubbub.o
+
+AMD_DAL_HUBBUB_DCN42 = $(addprefix $(AMDDALPATH)/dc/hubbub/dcn42/,$(HUBBUB_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_HUBBUB_DCN42)
+
endif
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 990d3cd8e050..ff9a1ae29474 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Advanced Micro Devices, Inc.
+ * Copyright 2016-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -441,6 +441,8 @@ struct dcn_hubbub_registers {
type DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_VALUE;\
type DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_ENABLE
+#define HUBBUB_REG_FIELD_LIST_DCN4_2(type) \
+ type URGENT_ZERO_SIZE_REQ_EN
struct dcn_hubbub_shift {
DCN_HUBBUB_REG_FIELD_LIST(uint8_t);
HUBBUB_STUTTER_REG_FIELD_LIST(uint8_t);
@@ -449,6 +451,7 @@ struct dcn_hubbub_shift {
HUBBUB_REG_FIELD_LIST_DCN32(uint8_t);
HUBBUB_REG_FIELD_LIST_DCN35(uint8_t);
HUBBUB_REG_FIELD_LIST_DCN4_01(uint8_t);
+ HUBBUB_REG_FIELD_LIST_DCN4_2(uint8_t);
};
@@ -460,6 +463,7 @@ struct dcn_hubbub_mask {
HUBBUB_REG_FIELD_LIST_DCN32(uint32_t);
HUBBUB_REG_FIELD_LIST_DCN35(uint32_t);
HUBBUB_REG_FIELD_LIST_DCN4_01(uint32_t);
+ HUBBUB_REG_FIELD_LIST_DCN4_2(uint8_t);
};
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c
index 5a03758e3de6..3c298192f359 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c
@@ -943,6 +943,7 @@ static void hubbub31_get_dchub_ref_freq(struct hubbub *hubbub,
unsigned int dccg_ref_freq_inKhz,
unsigned int *dchub_ref_freq_inKhz)
{
+ (void)dccg_ref_freq_inKhz;
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
uint32_t ref_div = 0;
uint32_t ref_en = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c
index 43ba399f4822..82d4e3e0e5e8 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c
@@ -259,6 +259,7 @@ void hubbub35_get_dchub_ref_freq(struct hubbub *hubbub,
unsigned int dccg_ref_freq_inKhz,
unsigned int *dchub_ref_freq_inKhz)
{
+ (void)dccg_ref_freq_inKhz;
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
uint32_t ref_div = 0;
uint32_t ref_en = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
index 941dce439e97..3b9542c08f3d 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
@@ -70,6 +70,7 @@ bool hubbub401_program_urgent_watermarks(
unsigned int refclk_mhz,
bool safe_to_lower)
{
+ (void)refclk_mhz;
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
bool wm_pending = false;
@@ -188,6 +189,7 @@ bool hubbub401_program_stutter_watermarks(
unsigned int refclk_mhz,
bool safe_to_lower)
{
+ (void)refclk_mhz;
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
bool wm_pending = false;
@@ -287,6 +289,7 @@ bool hubbub401_program_pstate_watermarks(
unsigned int refclk_mhz,
bool safe_to_lower)
{
+ (void)refclk_mhz;
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
bool wm_pending = false;
@@ -414,6 +417,7 @@ bool hubbub401_program_usr_watermarks(
unsigned int refclk_mhz,
bool safe_to_lower)
{
+ (void)refclk_mhz;
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
bool wm_pending = false;
@@ -1151,8 +1155,6 @@ void dcn401_program_compbuf_segments(struct hubbub *hubbub, unsigned compbuf_siz
{
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
- unsigned int cur_compbuf_size_seg = 0;
-
if (safe_to_increase || compbuf_size_seg <= hubbub2->compbuf_size_segments) {
if (compbuf_size_seg > hubbub2->compbuf_size_segments) {
REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100);
@@ -1165,8 +1167,6 @@ void dcn401_program_compbuf_segments(struct hubbub *hubbub, unsigned compbuf_siz
+ hubbub2->det3_size + compbuf_size_seg <= hubbub2->crb_size_segs);
REG_UPDATE(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, compbuf_size_seg);
hubbub2->compbuf_size_segments = compbuf_size_seg;
-
- ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &cur_compbuf_size_seg) && !cur_compbuf_size_seg);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c
new file mode 100644
index 000000000000..73b6b0ffcb74
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.c
@@ -0,0 +1,576 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dcn30/dcn30_hubbub.h"
+#include "dcn31/dcn31_hubbub.h"
+#include "dcn32/dcn32_hubbub.h"
+#include "dcn35/dcn35_hubbub.h"
+#include "dcn401/dcn401_hubbub.h"
+#include "dcn42/dcn42_hubbub.h"
+#include "dm_services.h"
+#include "reg_helper.h"
+
+#define DCN42_CRB_SEGMENT_SIZE_KB 64
+
+#define CTX \
+ hubbub2->base.ctx
+#define DC_LOGGER \
+ hubbub2->base.ctx->logger
+#define REG(reg)\
+ hubbub2->regs->reg
+
+#undef FN
+#define FN(reg_name, field_name) \
+ hubbub2->shifts->field_name, hubbub2->masks->field_name
+
+static bool hubbub42_program_urgent_watermarks(
+ struct hubbub *hubbub,
+ union dcn_watermark_set *watermarks,
+ bool safe_to_lower)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ bool wm_pending = false;
+
+ /* Repeat for water mark set A, B, C and D. */
+ /* clock state A */
+ if (safe_to_lower || watermarks->dcn4x.a.urgent > hubbub2->watermarks.dcn4x.a.urgent) {
+ hubbub2->watermarks.dcn4x.a.urgent = watermarks->dcn4x.a.urgent;
+ REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,
+ DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, watermarks->dcn4x.a.urgent);
+ } else if (watermarks->dcn4x.a.urgent < hubbub2->watermarks.dcn4x.a.urgent)
+ wm_pending = true;
+
+ /* determine the transfer time for a quantity of data for a particular requestor.*/
+ if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip) {
+ hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip = watermarks->dcn4x.a.frac_urg_bw_flip;
+ REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0,
+ DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->dcn4x.a.frac_urg_bw_flip);
+ } else if (watermarks->dcn4x.a.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.a.frac_urg_bw_flip)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.a.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom) {
+ hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom = watermarks->dcn4x.a.frac_urg_bw_nom;
+ REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0,
+ DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->dcn4x.a.frac_urg_bw_nom);
+ } else if (watermarks->dcn4x.a.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.a.frac_urg_bw_nom)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.a.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem) {
+ hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem = watermarks->dcn4x.a.refcyc_per_trip_to_mem;
+ REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0,
+ DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, watermarks->dcn4x.a.refcyc_per_trip_to_mem);
+ } else if (watermarks->dcn4x.a.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.a.refcyc_per_trip_to_mem)
+ wm_pending = true;
+
+ /* clock state B */
+ if (safe_to_lower || watermarks->dcn4x.b.urgent > hubbub2->watermarks.dcn4x.b.urgent) {
+ hubbub2->watermarks.dcn4x.b.urgent = watermarks->dcn4x.b.urgent;
+ REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0,
+ DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, watermarks->dcn4x.b.urgent);
+ } else if (watermarks->dcn4x.b.urgent < hubbub2->watermarks.dcn4x.b.urgent)
+ wm_pending = true;
+
+ /* determine the transfer time for a quantity of data for a particular requestor.*/
+ if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip) {
+ hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip = watermarks->dcn4x.b.frac_urg_bw_flip;
+ REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0,
+ DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->dcn4x.b.frac_urg_bw_flip);
+ } else if (watermarks->dcn4x.b.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.b.frac_urg_bw_flip)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.b.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom) {
+ hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom = watermarks->dcn4x.b.frac_urg_bw_nom;
+ REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0,
+ DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->dcn4x.b.frac_urg_bw_nom);
+ } else if (watermarks->dcn4x.b.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.b.frac_urg_bw_nom)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.b.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem) {
+ hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem = watermarks->dcn4x.b.refcyc_per_trip_to_mem;
+ REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0,
+ DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, watermarks->dcn4x.b.refcyc_per_trip_to_mem);
+ } else if (watermarks->dcn4x.b.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.b.refcyc_per_trip_to_mem)
+ wm_pending = true;
+
+ /* clock state C */
+ if (safe_to_lower || watermarks->dcn4x.c.urgent > hubbub2->watermarks.dcn4x.c.urgent) {
+ hubbub2->watermarks.dcn4x.c.urgent = watermarks->dcn4x.c.urgent;
+ REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0,
+ DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, watermarks->dcn4x.c.urgent);
+ } else if (watermarks->dcn4x.c.urgent < hubbub2->watermarks.dcn4x.c.urgent)
+ wm_pending = true;
+
+ /* determine the transfer time for a quantity of data for a particular requestor.*/
+ if (safe_to_lower || watermarks->dcn4x.c.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip) {
+ hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip = watermarks->dcn4x.c.frac_urg_bw_flip;
+ REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0,
+ DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->dcn4x.c.frac_urg_bw_flip);
+ } else if (watermarks->dcn4x.c.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.c.frac_urg_bw_flip)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.c.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom) {
+ hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom = watermarks->dcn4x.c.frac_urg_bw_nom;
+ REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0,
+ DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->dcn4x.c.frac_urg_bw_nom);
+ } else if (watermarks->dcn4x.c.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.c.frac_urg_bw_nom)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.c.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem) {
+ hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem = watermarks->dcn4x.c.refcyc_per_trip_to_mem;
+ REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0,
+ DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, watermarks->dcn4x.c.refcyc_per_trip_to_mem);
+ } else if (watermarks->dcn4x.c.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.c.refcyc_per_trip_to_mem)
+ wm_pending = true;
+
+ /* clock state D */
+ if (safe_to_lower || watermarks->dcn4x.d.urgent > hubbub2->watermarks.dcn4x.d.urgent) {
+ hubbub2->watermarks.dcn4x.d.urgent = watermarks->dcn4x.d.urgent;
+ REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0,
+ DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, watermarks->dcn4x.d.urgent);
+ } else if (watermarks->dcn4x.d.urgent < hubbub2->watermarks.dcn4x.d.urgent)
+ wm_pending = true;
+
+ /* determine the transfer time for a quantity of data for a particular requestor.*/
+ if (safe_to_lower || watermarks->dcn4x.d.frac_urg_bw_flip > hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip) {
+ hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip = watermarks->dcn4x.d.frac_urg_bw_flip;
+ REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0,
+ DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->dcn4x.d.frac_urg_bw_flip);
+ } else if (watermarks->dcn4x.d.frac_urg_bw_flip < hubbub2->watermarks.dcn4x.d.frac_urg_bw_flip)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.d.frac_urg_bw_nom > hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom) {
+ hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom = watermarks->dcn4x.d.frac_urg_bw_nom;
+ REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0,
+ DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->dcn4x.d.frac_urg_bw_nom);
+ } else if (watermarks->dcn4x.d.frac_urg_bw_nom < hubbub2->watermarks.dcn4x.d.frac_urg_bw_nom)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.d.refcyc_per_trip_to_mem > hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem) {
+ hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem = watermarks->dcn4x.d.refcyc_per_trip_to_mem;
+ REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0,
+ DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, watermarks->dcn4x.d.refcyc_per_trip_to_mem);
+ } else if (watermarks->dcn4x.d.refcyc_per_trip_to_mem < hubbub2->watermarks.dcn4x.d.refcyc_per_trip_to_mem)
+ wm_pending = true;
+
+ return wm_pending;
+}
+
+static bool hubbub42_program_stutter_watermarks(
+ struct hubbub *hubbub,
+ union dcn_watermark_set *watermarks,
+ bool safe_to_lower)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ bool wm_pending = false;
+
+ /* clock state A */
+ if (safe_to_lower || watermarks->dcn4x.a.sr_enter > hubbub2->watermarks.dcn4x.a.sr_enter) {
+ hubbub2->watermarks.dcn4x.a.sr_enter = watermarks->dcn4x.a.sr_enter;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, watermarks->dcn4x.a.sr_enter);
+ } else if (watermarks->dcn4x.a.sr_enter < hubbub2->watermarks.dcn4x.a.sr_enter)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.a.sr_exit > hubbub2->watermarks.dcn4x.a.sr_exit) {
+ hubbub2->watermarks.dcn4x.a.sr_exit = watermarks->dcn4x.a.sr_exit;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, watermarks->dcn4x.a.sr_exit);
+ } else if (watermarks->dcn4x.a.sr_exit < hubbub2->watermarks.dcn4x.a.sr_exit)
+ wm_pending = true;
+
+ /* clock state B */
+ if (safe_to_lower || watermarks->dcn4x.b.sr_enter > hubbub2->watermarks.dcn4x.b.sr_enter) {
+ hubbub2->watermarks.dcn4x.b.sr_enter = watermarks->dcn4x.b.sr_enter;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, watermarks->dcn4x.b.sr_enter);
+ } else if (watermarks->dcn4x.b.sr_enter < hubbub2->watermarks.dcn4x.b.sr_enter)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.b.sr_exit > hubbub2->watermarks.dcn4x.b.sr_exit) {
+ hubbub2->watermarks.dcn4x.b.sr_exit = watermarks->dcn4x.b.sr_exit;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, watermarks->dcn4x.b.sr_exit);
+ } else if (watermarks->dcn4x.b.sr_exit < hubbub2->watermarks.dcn4x.b.sr_exit)
+ wm_pending = true;
+
+ /* clock state C */
+ if (safe_to_lower || watermarks->dcn4x.c.sr_enter > hubbub2->watermarks.dcn4x.c.sr_enter) {
+ hubbub2->watermarks.dcn4x.c.sr_enter = watermarks->dcn4x.c.sr_enter;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, watermarks->dcn4x.c.sr_enter);
+ } else if (watermarks->dcn4x.c.sr_enter < hubbub2->watermarks.dcn4x.c.sr_enter)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.c.sr_exit > hubbub2->watermarks.dcn4x.c.sr_exit) {
+ hubbub2->watermarks.dcn4x.c.sr_exit = watermarks->dcn4x.c.sr_exit;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, watermarks->dcn4x.c.sr_exit);
+ } else if (watermarks->dcn4x.c.sr_exit < hubbub2->watermarks.dcn4x.c.sr_exit)
+ wm_pending = true;
+
+ /* clock state D */
+ if (safe_to_lower || watermarks->dcn4x.d.sr_enter > hubbub2->watermarks.dcn4x.d.sr_enter) {
+ hubbub2->watermarks.dcn4x.d.sr_enter = watermarks->dcn4x.d.sr_enter;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, watermarks->dcn4x.d.sr_enter);
+ } else if (watermarks->dcn4x.d.sr_enter < hubbub2->watermarks.dcn4x.d.sr_enter)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.d.sr_exit > hubbub2->watermarks.dcn4x.d.sr_exit) {
+ hubbub2->watermarks.dcn4x.d.sr_exit = watermarks->dcn4x.d.sr_exit;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, watermarks->dcn4x.d.sr_exit);
+ } else if (watermarks->dcn4x.d.sr_exit < hubbub2->watermarks.dcn4x.d.sr_exit)
+ wm_pending = true;
+
+ return wm_pending;
+}
+
+static bool hubbub42_program_pstate_watermarks(
+ struct hubbub *hubbub,
+ union dcn_watermark_set *watermarks,
+ bool safe_to_lower)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ bool wm_pending = false;
+
+ /* Section for UCLK_PSTATE_CHANGE_WATERMARKS */
+ /* UCLK state A */
+ if (safe_to_lower || watermarks->dcn4x.a.uclk_pstate > hubbub2->watermarks.dcn4x.a.uclk_pstate) {
+ hubbub2->watermarks.dcn4x.a.uclk_pstate = watermarks->dcn4x.a.uclk_pstate;
+ REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, 0,
+ DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.uclk_pstate);
+ } else if (watermarks->dcn4x.a.uclk_pstate < hubbub2->watermarks.dcn4x.a.uclk_pstate)
+ wm_pending = true;
+
+ /* UCLK state B */
+ if (safe_to_lower || watermarks->dcn4x.b.uclk_pstate > hubbub2->watermarks.dcn4x.b.uclk_pstate) {
+ hubbub2->watermarks.dcn4x.b.uclk_pstate = watermarks->dcn4x.b.uclk_pstate;
+ REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, 0,
+ DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.uclk_pstate);
+ } else if (watermarks->dcn4x.b.uclk_pstate < hubbub2->watermarks.dcn4x.b.uclk_pstate)
+ wm_pending = true;
+
+ /* UCLK state C */
+ if (safe_to_lower || watermarks->dcn4x.c.uclk_pstate > hubbub2->watermarks.dcn4x.c.uclk_pstate) {
+ hubbub2->watermarks.dcn4x.c.uclk_pstate = watermarks->dcn4x.c.uclk_pstate;
+ REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, 0,
+ DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, watermarks->dcn4x.c.uclk_pstate);
+ } else if (watermarks->dcn4x.c.uclk_pstate < hubbub2->watermarks.dcn4x.c.uclk_pstate)
+ wm_pending = true;
+
+ /* UCLK state D */
+ if (safe_to_lower || watermarks->dcn4x.d.uclk_pstate > hubbub2->watermarks.dcn4x.d.uclk_pstate) {
+ hubbub2->watermarks.dcn4x.d.uclk_pstate = watermarks->dcn4x.d.uclk_pstate;
+ REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, 0,
+ DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, watermarks->dcn4x.d.uclk_pstate);
+ } else if (watermarks->dcn4x.d.uclk_pstate < hubbub2->watermarks.dcn4x.d.uclk_pstate)
+ wm_pending = true;
+
+ /* Section for FCLK_PSTATE_CHANGE_WATERMARKS */
+ /* FCLK state A */
+ if (safe_to_lower || watermarks->dcn4x.a.fclk_pstate > hubbub2->watermarks.dcn4x.a.fclk_pstate) {
+ hubbub2->watermarks.dcn4x.a.fclk_pstate = watermarks->dcn4x.a.fclk_pstate;
+ REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, 0,
+ DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, watermarks->dcn4x.a.fclk_pstate);
+ } else if (watermarks->dcn4x.a.fclk_pstate < hubbub2->watermarks.dcn4x.a.fclk_pstate)
+ wm_pending = true;
+
+ /* FCLK state B */
+ if (safe_to_lower || watermarks->dcn4x.b.fclk_pstate > hubbub2->watermarks.dcn4x.b.fclk_pstate) {
+ hubbub2->watermarks.dcn4x.b.fclk_pstate = watermarks->dcn4x.b.fclk_pstate;
+ REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, 0,
+ DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, watermarks->dcn4x.b.fclk_pstate);
+ } else if (watermarks->dcn4x.b.fclk_pstate < hubbub2->watermarks.dcn4x.b.fclk_pstate)
+ wm_pending = true;
+
+ /* FCLK state C */
+ if (safe_to_lower || watermarks->dcn4x.c.fclk_pstate > hubbub2->watermarks.dcn4x.c.fclk_pstate) {
+ hubbub2->watermarks.dcn4x.c.fclk_pstate = watermarks->dcn4x.c.fclk_pstate;
+ REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, 0,
+ DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, watermarks->dcn4x.c.fclk_pstate);
+ } else if (watermarks->dcn4x.c.fclk_pstate < hubbub2->watermarks.dcn4x.c.fclk_pstate)
+ wm_pending = true;
+
+ /* FCLK state D */
+ if (safe_to_lower || watermarks->dcn4x.d.fclk_pstate > hubbub2->watermarks.dcn4x.d.fclk_pstate) {
+ hubbub2->watermarks.dcn4x.d.fclk_pstate = watermarks->dcn4x.d.fclk_pstate;
+ REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, 0,
+ DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, watermarks->dcn4x.d.fclk_pstate);
+ } else if (watermarks->dcn4x.d.fclk_pstate < hubbub2->watermarks.dcn4x.d.fclk_pstate)
+ wm_pending = true;
+
+ return wm_pending;
+}
+
+static bool hubbub42_program_usr_watermarks(
+ struct hubbub *hubbub,
+ union dcn_watermark_set *watermarks,
+ bool safe_to_lower)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ bool wm_pending = false;
+
+ /* clock state A */
+ if (safe_to_lower || watermarks->dcn4x.a.usr > hubbub2->watermarks.dcn4x.a.usr) {
+ hubbub2->watermarks.dcn4x.a.usr = watermarks->dcn4x.a.usr;
+ REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, 0,
+ DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, watermarks->dcn4x.a.usr);
+ } else if (watermarks->dcn4x.a.usr < hubbub2->watermarks.dcn4x.a.usr)
+ wm_pending = true;
+
+ /* clock state B */
+ if (safe_to_lower || watermarks->dcn4x.b.usr > hubbub2->watermarks.dcn4x.b.usr) {
+ hubbub2->watermarks.dcn4x.b.usr = watermarks->dcn4x.b.usr;
+ REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, 0,
+ DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, watermarks->dcn4x.b.usr);
+ } else if (watermarks->dcn4x.b.usr < hubbub2->watermarks.dcn4x.b.usr)
+ wm_pending = true;
+
+ /* clock state C */
+ if (safe_to_lower || watermarks->dcn4x.c.usr > hubbub2->watermarks.dcn4x.c.usr) {
+ hubbub2->watermarks.dcn4x.c.usr = watermarks->dcn4x.c.usr;
+ REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, 0,
+ DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, watermarks->dcn4x.c.usr);
+ } else if (watermarks->dcn4x.c.usr < hubbub2->watermarks.dcn4x.c.usr)
+ wm_pending = true;
+
+ /* clock state D */
+ if (safe_to_lower || watermarks->dcn4x.d.usr > hubbub2->watermarks.dcn4x.d.usr) {
+ hubbub2->watermarks.dcn4x.d.usr = watermarks->dcn4x.d.usr;
+ REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, 0,
+ DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, watermarks->dcn4x.d.usr);
+ } else if (watermarks->dcn4x.d.usr < hubbub2->watermarks.dcn4x.d.usr)
+ wm_pending = true;
+
+ return wm_pending;
+}
+
+static bool hubbub42_program_stutter_z8_watermarks(
+ struct hubbub *hubbub,
+ union dcn_watermark_set *watermarks,
+ bool safe_to_lower)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ bool wm_pending = false;
+
+ /* clock state A */
+ if (safe_to_lower || watermarks->dcn4x.a.sr_enter_z8 > hubbub2->watermarks.dcn4x.a.sr_enter_z8) {
+ hubbub2->watermarks.dcn4x.a.sr_enter_z8 = watermarks->dcn4x.a.sr_enter_z8;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, 0,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, watermarks->dcn4x.a.sr_enter_z8);
+ } else if (watermarks->dcn4x.a.sr_enter_z8 < hubbub2->watermarks.dcn4x.a.sr_enter_z8)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.a.sr_exit_z8 > hubbub2->watermarks.dcn4x.a.sr_exit_z8) {
+ hubbub2->watermarks.dcn4x.a.sr_exit_z8 = watermarks->dcn4x.a.sr_exit_z8;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, 0,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, watermarks->dcn4x.a.sr_exit_z8);
+ } else if (watermarks->dcn4x.a.sr_exit_z8 < hubbub2->watermarks.dcn4x.a.sr_exit_z8)
+ wm_pending = true;
+
+ /* clock state B */
+ if (safe_to_lower || watermarks->dcn4x.b.sr_enter_z8 > hubbub2->watermarks.dcn4x.b.sr_enter_z8) {
+ hubbub2->watermarks.dcn4x.b.sr_enter_z8 = watermarks->dcn4x.b.sr_enter_z8;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, 0,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, watermarks->dcn4x.b.sr_enter_z8);
+ } else if (watermarks->dcn4x.b.sr_enter_z8 < hubbub2->watermarks.dcn4x.b.sr_enter_z8)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.b.sr_exit_z8 > hubbub2->watermarks.dcn4x.b.sr_exit_z8) {
+ hubbub2->watermarks.dcn4x.b.sr_exit_z8 = watermarks->dcn4x.b.sr_exit_z8;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, 0,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, watermarks->dcn4x.b.sr_exit_z8);
+ } else if (watermarks->dcn4x.b.sr_exit_z8 < hubbub2->watermarks.dcn4x.b.sr_exit_z8)
+ wm_pending = true;
+
+ /* clock state C */
+ if (safe_to_lower || watermarks->dcn4x.c.sr_enter_z8 > hubbub2->watermarks.dcn4x.c.sr_enter_z8) {
+ hubbub2->watermarks.dcn4x.c.sr_enter_z8 = watermarks->dcn4x.c.sr_enter_z8;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, 0,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, watermarks->dcn4x.c.sr_enter_z8);
+ } else if (watermarks->dcn4x.c.sr_enter_z8 < hubbub2->watermarks.dcn4x.c.sr_enter_z8)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.c.sr_exit_z8 > hubbub2->watermarks.dcn4x.c.sr_exit_z8) {
+ hubbub2->watermarks.dcn4x.c.sr_exit_z8 = watermarks->dcn4x.c.sr_exit_z8;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, 0,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, watermarks->dcn4x.c.sr_exit_z8);
+ } else if (watermarks->dcn4x.c.sr_exit_z8 < hubbub2->watermarks.dcn4x.c.sr_exit_z8)
+ wm_pending = true;
+
+ /* clock state D */
+ if (safe_to_lower || watermarks->dcn4x.d.sr_enter_z8 > hubbub2->watermarks.dcn4x.d.sr_enter_z8) {
+ hubbub2->watermarks.dcn4x.d.sr_enter_z8 = watermarks->dcn4x.d.sr_enter_z8;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, 0,
+ DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, watermarks->dcn4x.d.sr_enter_z8);
+ } else if (watermarks->dcn4x.d.sr_enter_z8 < hubbub2->watermarks.dcn4x.d.sr_enter_z8)
+ wm_pending = true;
+
+ if (safe_to_lower || watermarks->dcn4x.d.sr_exit_z8 > hubbub2->watermarks.dcn4x.d.sr_exit_z8) {
+ hubbub2->watermarks.dcn4x.d.sr_exit_z8 = watermarks->dcn4x.d.sr_exit_z8;
+ REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, 0,
+ DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, watermarks->dcn4x.d.sr_exit_z8);
+ } else if (watermarks->dcn4x.d.sr_exit_z8 < hubbub2->watermarks.dcn4x.d.sr_exit_z8)
+ wm_pending = true;
+
+ return wm_pending;
+}
+
+static void hubbub42_allow_self_refresh_control(struct hubbub *hubbub, bool allow)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+ /*
+ * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 1 means do not allow stutter
+ * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 means allow stutter
+ */
+
+ REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL,
+ DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0,
+ DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, !allow);
+}
+static void hubbub42_set_sdp_control(struct hubbub *hubbub, bool dc_control)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+ REG_UPDATE(DCHUBBUB_SDPIF_CFG0,
+ SDPIF_PORT_CONTROL, dc_control);
+}
+
+static bool hubbub42_program_watermarks(
+ struct hubbub *hubbub,
+ union dcn_watermark_set *watermarks,
+ unsigned int refclk_mhz,
+ bool safe_to_lower)
+{
+ bool wm_pending = false;
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+ if (!safe_to_lower && hubbub->ctx->dc->debug.disable_stutter_for_wm_program) {
+ /* before raising watermarks, SDP control give to DF, stutter must be disabled */
+ wm_pending = true;
+ hubbub42_set_sdp_control(hubbub, false);
+ hubbub42_allow_self_refresh_control(hubbub, false);
+ }
+ if (hubbub42_program_urgent_watermarks(hubbub, watermarks, safe_to_lower))
+ wm_pending = true;
+
+ if (hubbub42_program_stutter_watermarks(hubbub, watermarks, safe_to_lower))
+ wm_pending = true;
+
+ if (hubbub42_program_pstate_watermarks(hubbub, watermarks, safe_to_lower))
+ wm_pending = true;
+
+ if (hubbub42_program_usr_watermarks(hubbub, watermarks, safe_to_lower))
+ wm_pending = true;
+
+ if (hubbub42_program_stutter_z8_watermarks(hubbub, watermarks, safe_to_lower))
+ wm_pending = true;
+
+ REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,
+ DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
+ REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
+ DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0xFF,
+ DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);/*hw delta*/
+ REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF);
+
+ if (safe_to_lower || hubbub->ctx->dc->debug.disable_stutter)
+ hubbub42_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
+ if (safe_to_lower && hubbub->ctx->dc->debug.disable_stutter_for_wm_program) {
+ hubbub42_set_sdp_control(hubbub, true);
+ }
+ hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow);
+
+ return wm_pending;
+}
+
+static void hubbub42_set_request_limit(struct hubbub *hubbub, int memory_channel_count, int words_per_channel)
+{
+ (void)memory_channel_count;
+ (void)words_per_channel;
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ uint32_t request_limit = 96; //MAX(12 * memory_channel_count, 96);
+
+ REG_UPDATE(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, request_limit);
+}
+
+static bool dcn42_program_arbiter(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs,
+ bool safe_to_lower)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+ bool wm_pending = false;
+ uint32_t temp;
+
+ /* request backpressure and outstanding return threshold (unused)*/
+ //REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, arb_regs->req_stall_threshold);
+
+ /* 401 delta: do not update P-State stall threshold (handled by fw) */
+ // REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, arb_regs->pstate_stall_threshold);
+
+ if (safe_to_lower || arb_regs->allow_sdpif_rate_limit_when_cstate_req > hubbub2->allow_sdpif_rate_limit_when_cstate_req) {
+ hubbub2->allow_sdpif_rate_limit_when_cstate_req = arb_regs->allow_sdpif_rate_limit_when_cstate_req;
+
+ /* only update the required bits */
+ REG_GET(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, &temp);
+ if (hubbub2->allow_sdpif_rate_limit_when_cstate_req) {
+ temp |= (1 << 5);
+ } else {
+ temp &= ~(1 << 5);
+ }
+ REG_UPDATE(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, temp);
+ } else {
+ wm_pending = true;
+ }
+
+ return wm_pending;
+}
+
+static const struct hubbub_funcs hubbub42_funcs = {
+ .update_dchub = hubbub2_update_dchub,
+ .init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx,
+ .init_vm_ctx = hubbub2_init_vm_ctx,
+ .dcc_support_swizzle = hubbub3_dcc_support_swizzle,
+ .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,
+ .get_dcc_compression_cap = hubbub3_get_dcc_compression_cap,
+ .wm_read_state = hubbub35_wm_read_state,
+ .get_dchub_ref_freq = hubbub35_get_dchub_ref_freq,
+ .program_watermarks = hubbub42_program_watermarks,
+ .allow_self_refresh_control = hubbub42_allow_self_refresh_control,
+ .is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,
+ .force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes,
+ .force_pstate_change_control = hubbub3_force_pstate_change_control,
+ .init_watermarks = hubbub35_init_watermarks,
+ .init_crb = dcn401_init_crb,
+ .dchvm_init = dcn35_dchvm_init,
+ .hubbub_read_state = hubbub2_read_state,
+ .force_usr_retraining_allow = hubbub32_force_usr_retraining_allow,
+ .set_request_limit = hubbub42_set_request_limit,
+ .program_det_segments = dcn401_program_det_segments,
+ .program_compbuf_segments = dcn401_program_compbuf_segments,
+ .wait_for_det_update = dcn401_wait_for_det_update,
+ .program_arbiter = dcn42_program_arbiter,
+ .hubbub_read_reg_state = hubbub3_read_reg_state
+};
+
+void hubbub42_construct(struct dcn20_hubbub *hubbub2,
+ struct dc_context *ctx,
+ const struct dcn_hubbub_registers *hubbub_regs,
+ const struct dcn_hubbub_shift *hubbub_shift,
+ const struct dcn_hubbub_mask *hubbub_mask,
+ int det_size_kb,
+ int pixel_chunk_size_kb,
+ int config_return_buffer_size_kb)
+{
+ hubbub2->base.ctx = ctx;
+ hubbub2->base.funcs = &hubbub42_funcs;
+ hubbub2->regs = hubbub_regs;
+ hubbub2->shifts = hubbub_shift;
+ hubbub2->masks = hubbub_mask;
+
+ hubbub2->detile_buf_size = det_size_kb * 1024;
+ hubbub2->pixel_chunk_size = pixel_chunk_size_kb * 1024;
+ hubbub2->crb_size_segs = config_return_buffer_size_kb / DCN42_CRB_SEGMENT_SIZE_KB;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.h
new file mode 100644
index 000000000000..926ddc156a2b
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn42/dcn42_hubbub.h
@@ -0,0 +1,268 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_HUBBUB_DCN42_H__
+#define __DC_HUBBUB_DCN42_H__
+
+#include "dcn32/dcn32_hubbub.h"
+
+#define DCN42_CRB_SIZE_KB 1792
+#define DCN42_DEFAULT_DET_SIZE 320
+#define DCN42_CRB_SEGMENT_SIZE_KB 64
+
+#define HUBBUB_REG_LIST_DCN42(id)\
+ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A),\
+ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B),\
+ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C),\
+ SR(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D),\
+ SR(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL),\
+ SR(DCHUBBUB_ARB_DRAM_STATE_CNTL),\
+ SR(DCHUBBUB_ARB_SAT_LEVEL),\
+ SR(DCHUBBUB_ARB_DF_REQ_OUTSTAND),\
+ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \
+ SR(DCHUBBUB_SOFT_RESET),\
+ SR(DCHUBBUB_CRC_CTRL), \
+ SR(DCN_VM_FB_LOCATION_BASE),\
+ SR(DCN_VM_FB_LOCATION_TOP),\
+ SR(DCN_VM_FB_OFFSET),\
+ SR(DCN_VM_AGP_BOT),\
+ SR(DCN_VM_AGP_TOP),\
+ SR(DCN_VM_AGP_BASE),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C),\
+ SR(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D),\
+ SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A),\
+ SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B),\
+ SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C),\
+ SR(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D),\
+ SR(DCHUBBUB_DET0_CTRL),\
+ SR(DCHUBBUB_DET1_CTRL),\
+ SR(DCHUBBUB_DET2_CTRL),\
+ SR(DCHUBBUB_DET3_CTRL),\
+ SR(DCHUBBUB_COMPBUF_CTRL),\
+ SR(COMPBUF_RESERVED_SPACE),\
+ SR(DCHUBBUB_DEBUG_CTRL_0),\
+ SR(DCHUBBUB_ARB_USR_RETRAINING_CNTL),\
+ SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A),\
+ SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B),\
+ SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C),\
+ SR(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D),\
+ SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A),\
+ SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B),\
+ SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C),\
+ SR(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D),\
+ SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A),\
+ SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B),\
+ SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C),\
+ SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D),\
+ SR(DCN_VM_FAULT_ADDR_MSB),\
+ SR(DCN_VM_FAULT_ADDR_LSB),\
+ SR(DCN_VM_FAULT_CNTL),\
+ SR(DCN_VM_FAULT_STATUS),\
+ SR(SDPIF_REQUEST_RATE_LIMIT),\
+ SR(DCHUBBUB_CLOCK_CNTL),\
+ SR(DCHUBBUB_SDPIF_CFG0),\
+ SR(DCHUBBUB_SDPIF_CFG1),\
+ SR(DCHUBBUB_MEM_PWR_MODE_CTRL),\
+ SR(DCHUBBUB_ARB_HOSTVM_CNTL),\
+ SR(DCHVM_CTRL0),\
+ SR(DCHVM_MEM_CTRL),\
+ SR(DCHVM_CLK_CTRL),\
+ SR(DCHVM_RIOMMU_CTRL0),\
+ SR(DCHVM_RIOMMU_STAT0),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D),\
+ SR(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D),\
+ SR(DCHUBBUB_ARB_QOS_FORCE)
+
+#define HUBBUB_MASK_SH_LIST_DCN4_2(mask_sh)\
+ HUBBUB_MASK_SH_LIST_DCN32(mask_sh), \
+ HUBBUB_SF(DCHVM_CTRL0, HOSTVM_INIT_REQ, mask_sh),\
+ HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_PWR_REQ_DIS, mask_sh),\
+ HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_FORCE_REQ, mask_sh),\
+ HUBBUB_SF(DCHVM_MEM_CTRL, HVM_GPUVMRET_POWER_STATUS, mask_sh),\
+ HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DISPCLK_R_GATE_DIS, mask_sh),\
+ HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DISPCLK_G_GATE_DIS, mask_sh),\
+ HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DCFCLK_R_GATE_DIS, mask_sh),\
+ HUBBUB_SF(DCHVM_CLK_CTRL, HVM_DCFCLK_G_GATE_DIS, mask_sh),\
+ HUBBUB_SF(DCHVM_CLK_CTRL, TR_REQ_REQCLKREQ_MODE, mask_sh),\
+ HUBBUB_SF(DCHVM_CLK_CTRL, TW_RSP_COMPCLKREQ_MODE, mask_sh),\
+ HUBBUB_SF(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, mask_sh),\
+ HUBBUB_SF(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, mask_sh),\
+ HUBBUB_SF(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, mask_sh),\
+ HUBBUB_SF(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, mask_sh),\
+ HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_64B, mask_sh),\
+ HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_ZS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DCHUBBUB_FGCG_REP_DIS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MAX_REQ_OUTSTAND, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_CSTATE_DEEPSLEEP_LEGACY_MODE, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_SOFT_RESET, DCHUBBUB_GLOBAL_SOFT_RESET, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_REQUEST, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, DCHUBBUB_ARB_WATERMARK_CHANGE_DONE_INTERRUPT_DISABLE, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_VALUE, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_DCFCLK_DEEP_SLEEP_FORCE_ENABLE, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_VALUE, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DRAM_STATE_CNTL, DCHUBBUB_ARB_ALLOW_PSTATE_CHANGE_FORCE_ENABLE, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_HOSTVM_CNTL, DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_SAT_LEVEL, DCHUBBUB_ARB_SAT_LEVEL, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MIN_REQ_OUTSTAND, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DF_REQ_OUTSTAND, DCHUBBUB_ARB_MAX_REQ_OUTSTAND, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \
+ HUBBUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FB_LOCATION_TOP, FB_TOP, mask_sh), \
+ HUBBUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET, mask_sh), \
+ HUBBUB_SF(DCN_VM_AGP_BOT, AGP_BOT, mask_sh), \
+ HUBBUB_SF(DCN_VM_AGP_TOP, AGP_TOP, mask_sh), \
+ HUBBUB_SF(DCN_VM_AGP_BASE, AGP_BASE, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_DEBUG_CTRL_0, DET_DEPTH, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_DET0_CTRL, DET0_SIZE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_DET1_CTRL, DET1_SIZE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_DET2_CTRL, DET2_SIZE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_DET3_CTRL, DET3_SIZE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, mask_sh),\
+ HUBBUB_SF(COMPBUF_RESERVED_SPACE, COMPBUF_RESERVED_SPACE_64B, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_VALUE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_ENABLE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_DO_NOT_FORCE_ALLOW_USR_RETRAINING_DURING_PSTATE_CHANGE_REQUEST, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_CNTL, DCHUBBUB_ARB_DO_NOT_FORCE_ALLOW_USR_RETRAINING_DURING_PRE_CSTATE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_A, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_B, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_A, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_B, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C, mask_sh), \
+ HUBBUB_SF(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_ADDR_MSB, DCN_VM_FAULT_ADDR_MSB, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_ADDR_LSB, DCN_VM_FAULT_ADDR_LSB, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_CLEAR, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_STATUS_MODE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_ERROR_INTERRUPT_ENABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_RANGE_FAULT_DISABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_CNTL, DCN_VM_PRQ_FAULT_DISABLE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_STATUS, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh),\
+ HUBBUB_SF(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DISPCLK_R_DCHUBBUB_GATE_DIS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CLOCK_CNTL, DCFCLK_R_DCHUBBUB_GATE_DIS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_SDPIF_CFG0, SDPIF_PORT_CONTROL, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_SDPIF_CFG1, SDPIF_MAX_NUM_OUTSTANDING, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_MEM_PWR_MODE_CTRL, DET_MEM_PWR_LS_MODE, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_ERROR_STATUS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_DETECTION_EN, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_TIMER_RESET, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_STATUS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_CLEAR, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, URGENT_ZERO_SIZE_REQ_EN, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, CSTATE_SWATH_CHK_GOOD_MODE, mask_sh)
+
+void hubbub42_construct(struct dcn20_hubbub *hubbub2,
+ struct dc_context *ctx,
+ const struct dcn_hubbub_registers *hubbub_regs,
+ const struct dcn_hubbub_shift *hubbub_shift,
+ const struct dcn_hubbub_mask *hubbub_mask,
+ int det_size_kb,
+ int pixel_chunk_size_kb,
+ int config_return_buffer_size_kb);
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/Makefile b/drivers/gpu/drm/amd/display/dc/hubp/Makefile
index a2d1128de7a1..e0799bb873e6 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/hubp/Makefile
@@ -1,5 +1,5 @@
-# Copyright 2022 Advanced Micro Devices, Inc.
+# Copyright 2022-2026 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -94,4 +94,12 @@ AMD_DAL_HUBP_DCN401 = $(addprefix $(AMDDALPATH)/dc/hubp/dcn401/,$(HUBP_DCN401))
AMD_DISPLAY_FILES += $(AMD_DAL_HUBP_DCN401)
+###############################################################################
+
+HUBP_DCN42 = dcn42_hubp.o
+
+AMD_DAL_HUBP_DCN42 = $(addprefix $(AMDDALPATH)/dc/hubp/dcn42/,$(HUBP_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_HUBP_DCN42)
+
endif
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c
index 6378e3fd7249..7c97a774141f 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn10/dcn10_hubp.c
@@ -143,6 +143,7 @@ void hubp1_program_tiling(
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
+ (void)pixel_format;
struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
REG_UPDATE_6(DCSURF_ADDR_CONFIG,
@@ -563,6 +564,7 @@ void hubp1_program_surface_config(
bool horizontal_mirror,
unsigned int compat_level)
{
+ (void)compat_level;
hubp1_dcc_control(hubp, dcc->enable, dcc->independent_64b_blks);
hubp1_program_tiling(hubp, tiling_info, format);
hubp1_program_size(hubp, format, plane_size, dcc);
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c
index 92288de4cc10..ceee5165fd6a 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn20/dcn20_hubp.c
@@ -313,6 +313,7 @@ static void hubp2_program_tiling(
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
+ (void)pixel_format;
REG_UPDATE_3(DCSURF_ADDR_CONFIG,
NUM_PIPES, log_2(info->gfx9.num_pipes),
PIPE_INTERLEAVE, info->gfx9.pipe_interleave,
@@ -557,6 +558,7 @@ void hubp2_program_surface_config(
bool horizontal_mirror,
unsigned int compat_level)
{
+ (void)compat_level;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
hubp2_dcc_control(hubp, dcc->enable, dcc->independent_64b_blks);
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 7062e6653062..80be394a8852 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-17 Advanced Micro Devices, Inc.
+ * Copyright 2012-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -288,16 +288,22 @@
type MCACHEID_MALL_PREF_2H_P1;\
type HUBP_FGCG_REP_DIS
+#define DCN42_HUBP_REG_FIELD_VARIABLE_LIST(type) \
+ type HUBP_3DLUT_CROSSBAR_SEL_G;\
+ type HUBP_3DLUT_CROSSBAR_SEL_B;\
+ type HUBP_3DLUT_CROSSBAR_SEL_R
struct dcn_hubp2_registers {
DCN401_HUBP_REG_COMMON_VARIABLE_LIST;
};
struct dcn_hubp2_shift {
DCN401_HUBP_REG_FIELD_VARIABLE_LIST(uint8_t);
+ DCN42_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);
};
struct dcn20_hubp {
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c
index 0cc6f4558989..e2708e30eb1b 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn30/dcn30_hubp.c
@@ -321,6 +321,7 @@ void hubp3_program_tiling(
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
+ (void)pixel_format;
REG_UPDATE_4(DCSURF_ADDR_CONFIG,
NUM_PIPES, log_2(info->gfx9.num_pipes),
PIPE_INTERLEAVE, info->gfx9.pipe_interleave,
@@ -418,6 +419,7 @@ void hubp3_program_surface_config(
bool horizontal_mirror,
unsigned int compat_level)
{
+ (void)compat_level;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
hubp3_dcc_control_sienna_cichlid(hubp, dcc);
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c b/drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c
index 79c583e258c7..c879f4901c7d 100644
--- a/drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn35/dcn35_hubp.c
@@ -179,6 +179,7 @@ void hubp35_program_surface_config(
bool horizontal_mirror,
unsigned int compat_level)
{
+ (void)compat_level;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
hubp3_dcc_control_sienna_cichlid(hubp, dcc);
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 c205500290ec..5a816442deee 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 @@ int 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);
+ 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_width(struct hubp *hubp, enum hubp_3dlut_fl_width width)
+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_WIDTH, width);
-}
+ 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_tmz_protected(struct hubp *hubp, uint8_t protection_bits)
-{
- struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
-
- REG_UPDATE(HUBP_3DLUT_CONTROL, HUBP_3DLUT_TMZ, protection_bits);
-}
-
-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;
+
+ 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;
+ }
- uint32_t mpc_width = {(cfg->width == 17) ? 0 : 1};
- uint32_t width = {cfg->width};
+ 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);
- if (cfg->layout == DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR)
- width = (cfg->width == 17) ? 4916 : 35940;
+ 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)
@@ -584,6 +657,7 @@ void hubp401_program_tiling(
const struct dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
+ (void)pixel_format;
/* DCSURF_ADDR_CONFIG still shows up in reg spec, but does not need to be programmed for DCN4x
* All 4 fields NUM_PIPES, PIPE_INTERLEAVE, MAX_COMPRESSED_FRAGS and NUM_PKRS are irrelevant.
*
@@ -598,6 +672,7 @@ void hubp401_program_size(
const struct plane_size *plane_size,
struct dc_plane_dcc_param *dcc)
{
+ (void)dcc;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
uint32_t pitch, pitch_c;
bool use_pitch_c = false;
@@ -636,6 +711,7 @@ void hubp401_program_surface_config(
bool horizontal_mirror,
unsigned int compat_level)
{
+ (void)compat_level;
struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
hubp401_dcc_control(hubp, dcc);
@@ -739,9 +815,8 @@ void hubp401_cursor_set_position(
int x_pos_viewport = 0;
int x_hot_viewport = 0;
uint32_t cur_en = pos->enable ? 1 : 0;
-
+ uint32_t x_hotspot_clamped = pos->x_hotspot;
hubp->curs_pos = *pos;
-
/* Recout is zero for pipes if the entire dst_rect is contained
* within preceeding ODM slices.
*/
@@ -772,6 +847,8 @@ void hubp401_cursor_set_position(
ASSERT(param->h_scale_ratio.value);
+ if (x_hotspot_clamped > 0xFF)
+ x_hotspot_clamped = 0xFF;
if (param->h_scale_ratio.value)
dst_x_offset = dc_fixpt_floor(dc_fixpt_div(
dc_fixpt_from_int(dst_x_offset),
@@ -792,7 +869,7 @@ void hubp401_cursor_set_position(
CURSOR_Y_POSITION, pos->y);
REG_SET_2(CURSOR_HOT_SPOT, 0,
- CURSOR_HOT_SPOT_X, pos->x_hotspot,
+ CURSOR_HOT_SPOT_X, x_hotspot_clamped,
CURSOR_HOT_SPOT_Y, pos->y_hotspot);
REG_SET(CURSOR_DST_OFFSET, 0,
@@ -1058,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 4570b8016de5..043948f64b86 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 @@ int 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
new file mode 100644
index 000000000000..ad6badcceb12
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.c
@@ -0,0 +1,742 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dcn401/dcn401_hubp.h"
+#include "dcn42_hubp.h"
+#include "reg_helper.h"
+
+#define REG(reg) \
+ hubp2->hubp_regs->reg
+
+#define CTX \
+ hubp2->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+ hubp2->hubp_shift->field_name, hubp2->hubp_mask->field_name
+
+static void hubp42_set_fgcg(struct hubp *hubp, bool enable)
+{
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+ REG_UPDATE(HUBP_CLK_CNTL, HUBP_FGCG_REP_DIS, !enable);
+}
+
+static void hubp42_init(struct hubp *hubp)
+{
+ hubp3_init(hubp);
+
+ hubp42_set_fgcg(hubp, hubp->ctx->dc->debug.enable_fine_grain_clock_gating.bits.dchub);
+
+ /*do nothing for now for dcn3.5 or later*/
+}
+
+static void hubp42_program_pixel_format(
+ struct hubp *hubp,
+ enum surface_pixel_format format)
+{
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+ uint32_t green_bar = 1;
+ uint32_t red_bar = 3;
+ uint32_t blue_bar = 2;
+
+ /* swap for ABGR format */
+ if (format == SURFACE_PIXEL_FORMAT_GRPH_ABGR8888
+ || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010
+ || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS
+ || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616
+ || format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
+ red_bar = 2;
+ blue_bar = 3;
+ }
+
+ REG_UPDATE_3(HUBPRET_CONTROL,
+ CROSSBAR_SRC_Y_G, green_bar,
+ CROSSBAR_SRC_CB_B, blue_bar,
+ CROSSBAR_SRC_CR_R, red_bar);
+
+ /* Mapping is same as ipp programming (cnvc) */
+
+ switch (format) {
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 1);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 3);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 8);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 10);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: /* we use crossbar already */
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 26); /* ARGB16161616_UNORM */
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:/*we use crossbar already*/
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 24);
+ break;
+
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 65);
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 64);
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 67);
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 66);
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 12);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 112);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FIX:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 113);
+ break;
+ case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 114);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 118);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_BGR101111_FLOAT:
+ REG_UPDATE(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 119);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGBE:
+ REG_UPDATE_2(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 116,
+ ALPHA_PLANE_EN, 0);
+ break;
+ case SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA:
+ REG_UPDATE_2(DCSURF_SURFACE_CONFIG,
+ SURFACE_PIXEL_FORMAT, 116,
+ ALPHA_PLANE_EN, 1);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ break;
+ }
+
+ /* don't see the need of program the xbar in DCN 1.0 */
+}
+
+static void hubp42_program_deadline(
+ struct hubp *hubp,
+ struct dml2_display_dlg_regs *dlg_attr,
+ struct dml2_display_ttu_regs *ttu_attr)
+{
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+ /* put DLG in mission mode */
+ REG_WRITE(HUBPREQ_DEBUG_DB, 0);
+
+ /* DLG - Per hubp */
+ REG_SET_2(BLANK_OFFSET_0, 0,
+ REFCYC_H_BLANK_END, dlg_attr->refcyc_h_blank_end,
+ DLG_V_BLANK_END, dlg_attr->dlg_vblank_end);
+
+ REG_SET(BLANK_OFFSET_1, 0,
+ MIN_DST_Y_NEXT_START, dlg_attr->min_dst_y_next_start);
+
+ REG_SET(DST_DIMENSIONS, 0,
+ REFCYC_PER_HTOTAL, dlg_attr->refcyc_per_htotal);
+
+ REG_SET_2(DST_AFTER_SCALER, 0,
+ REFCYC_X_AFTER_SCALER, dlg_attr->refcyc_x_after_scaler,
+ DST_Y_AFTER_SCALER, dlg_attr->dst_y_after_scaler);
+
+ REG_SET(REF_FREQ_TO_PIX_FREQ, 0,
+ REF_FREQ_TO_PIX_FREQ, dlg_attr->ref_freq_to_pix_freq);
+
+ /* DLG - Per luma/chroma */
+ REG_SET(VBLANK_PARAMETERS_1, 0,
+ REFCYC_PER_PTE_GROUP_VBLANK_L, dlg_attr->refcyc_per_pte_group_vblank_l);
+
+ if (REG(NOM_PARAMETERS_0))
+ REG_SET(NOM_PARAMETERS_0, 0,
+ DST_Y_PER_PTE_ROW_NOM_L, dlg_attr->dst_y_per_pte_row_nom_l);
+
+ if (REG(NOM_PARAMETERS_1))
+ REG_SET(NOM_PARAMETERS_1, 0,
+ REFCYC_PER_PTE_GROUP_NOM_L, dlg_attr->refcyc_per_pte_group_nom_l);
+
+ REG_SET(NOM_PARAMETERS_4, 0,
+ DST_Y_PER_META_ROW_NOM_L, dlg_attr->dst_y_per_meta_row_nom_l);
+
+ REG_SET(NOM_PARAMETERS_5, 0,
+ REFCYC_PER_META_CHUNK_NOM_L, dlg_attr->refcyc_per_meta_chunk_nom_l);
+
+ REG_SET_2(PER_LINE_DELIVERY, 0,
+ REFCYC_PER_LINE_DELIVERY_L, dlg_attr->refcyc_per_line_delivery_l,
+ REFCYC_PER_LINE_DELIVERY_C, dlg_attr->refcyc_per_line_delivery_c);
+
+ REG_SET(VBLANK_PARAMETERS_2, 0,
+ REFCYC_PER_PTE_GROUP_VBLANK_C, dlg_attr->refcyc_per_pte_group_vblank_c);
+
+ if (REG(NOM_PARAMETERS_2))
+ REG_SET(NOM_PARAMETERS_2, 0,
+ DST_Y_PER_PTE_ROW_NOM_C, dlg_attr->dst_y_per_pte_row_nom_c);
+
+ if (REG(NOM_PARAMETERS_3))
+ REG_SET(NOM_PARAMETERS_3, 0,
+ REFCYC_PER_PTE_GROUP_NOM_C, dlg_attr->refcyc_per_pte_group_nom_c);
+
+ REG_SET(NOM_PARAMETERS_6, 0,
+ DST_Y_PER_META_ROW_NOM_C, dlg_attr->dst_y_per_meta_row_nom_c);
+
+ REG_SET(NOM_PARAMETERS_7, 0,
+ REFCYC_PER_META_CHUNK_NOM_C, dlg_attr->refcyc_per_meta_chunk_nom_c);
+
+ /* TTU - per hubp */
+ REG_SET_2(DCN_TTU_QOS_WM, 0,
+ QoS_LEVEL_LOW_WM, ttu_attr->qos_level_low_wm,
+ QoS_LEVEL_HIGH_WM, ttu_attr->qos_level_high_wm);
+
+ /* TTU - per luma/chroma */
+ /* Assumed surf0 is luma and 1 is chroma */
+
+ REG_SET_3(DCN_SURF0_TTU_CNTL0, 0,
+ REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_l,
+ QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_l,
+ QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_l);
+
+ REG_SET_3(DCN_SURF1_TTU_CNTL0, 0,
+ REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_c,
+ QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_c,
+ QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_c);
+
+ REG_SET_3(DCN_CUR0_TTU_CNTL0, 0,
+ REFCYC_PER_REQ_DELIVERY, ttu_attr->refcyc_per_req_delivery_cur0,
+ QoS_LEVEL_FIXED, ttu_attr->qos_level_fixed_cur0,
+ QoS_RAMP_DISABLE, ttu_attr->qos_ramp_disable_cur0);
+
+ REG_SET(FLIP_PARAMETERS_1, 0,
+ REFCYC_PER_PTE_GROUP_FLIP_L, dlg_attr->refcyc_per_pte_group_flip_l);
+ REG_SET(HUBP_3DLUT_DLG_PARAM, 0, REFCYC_PER_3DLUT_GROUP, dlg_attr->refcyc_per_tdlut_group);
+
+ REG_UPDATE(DCN_DMDATA_VM_CNTL,
+ REFCYC_PER_VM_DMDATA, dlg_attr->refcyc_per_vm_dmdata);
+}
+
+void hubp42_program_requestor(
+ struct hubp *hubp,
+ struct dml2_display_rq_regs *rq_regs)
+{
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+ REG_UPDATE(HUBPRET_CONTROL,
+ DET_BUF_PLANE1_BASE_ADDRESS, rq_regs->plane1_base_address);
+ REG_SET_4(DCN_EXPANSION_MODE, 0,
+ DRQ_EXPANSION_MODE, rq_regs->drq_expansion_mode,
+ PRQ_EXPANSION_MODE, rq_regs->prq_expansion_mode,
+ MRQ_EXPANSION_MODE, rq_regs->mrq_expansion_mode,
+ CRQ_EXPANSION_MODE, rq_regs->crq_expansion_mode);
+ REG_SET_8(DCHUBP_REQ_SIZE_CONFIG, 0,
+ CHUNK_SIZE, rq_regs->rq_regs_l.chunk_size,
+ MIN_CHUNK_SIZE, rq_regs->rq_regs_l.min_chunk_size,
+ META_CHUNK_SIZE, rq_regs->rq_regs_l.meta_chunk_size,
+ MIN_META_CHUNK_SIZE, rq_regs->rq_regs_l.min_meta_chunk_size,
+ DPTE_GROUP_SIZE, rq_regs->rq_regs_l.dpte_group_size,
+ VM_GROUP_SIZE, rq_regs->rq_regs_l.mpte_group_size,
+ SWATH_HEIGHT, rq_regs->rq_regs_l.swath_height,
+ PTE_ROW_HEIGHT_LINEAR, rq_regs->rq_regs_l.pte_row_height_linear);
+ REG_SET_7(DCHUBP_REQ_SIZE_CONFIG_C, 0,
+ CHUNK_SIZE_C, rq_regs->rq_regs_c.chunk_size,
+ MIN_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_chunk_size,
+ META_CHUNK_SIZE_C, rq_regs->rq_regs_c.meta_chunk_size,
+ MIN_META_CHUNK_SIZE_C, rq_regs->rq_regs_c.min_meta_chunk_size,
+ DPTE_GROUP_SIZE_C, rq_regs->rq_regs_c.dpte_group_size,
+ SWATH_HEIGHT_C, rq_regs->rq_regs_c.swath_height,
+ PTE_ROW_HEIGHT_LINEAR_C, rq_regs->rq_regs_c.pte_row_height_linear);
+}
+
+
+void hubp42_setup(
+ struct hubp *hubp,
+ struct dml2_dchub_per_pipe_register_set *pipe_regs,
+ union dml2_global_sync_programming *pipe_global_sync,
+ struct dc_crtc_timing *timing)
+{
+ /* otg is locked when this func is called. Register are double buffered.
+ * disable the requestors is not needed
+ */
+ hubp401_vready_at_or_After_vsync(hubp, pipe_global_sync, timing);
+ hubp42_program_requestor(hubp, &pipe_regs->rq_regs);
+ hubp42_program_deadline(hubp, &pipe_regs->dlg_regs, &pipe_regs->ttu_regs);
+}
+static void hubp42_program_surface_config(
+ struct hubp *hubp,
+ enum surface_pixel_format format,
+ struct dc_tiling_info *tiling_info,
+ struct plane_size *plane_size,
+ enum dc_rotation_angle rotation,
+ struct dc_plane_dcc_param *dcc,
+ bool horizontal_mirror,
+ unsigned int compat_level)
+{
+ (void)compat_level;
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+ hubp3_dcc_control_sienna_cichlid(hubp, dcc);
+ hubp3_program_tiling(hubp2, tiling_info, format);
+ hubp2_program_size(hubp, format, plane_size, dcc);
+ hubp2_program_rotation(hubp, rotation, horizontal_mirror);
+ hubp42_program_pixel_format(hubp, format);
+}
+
+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,
+ 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,
+ bool flip_immediate)
+{
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+
+ //program flip type
+ REG_UPDATE(DCSURF_FLIP_CONTROL,
+ SURFACE_FLIP_TYPE, flip_immediate);
+
+ // Program VMID reg
+ if (flip_immediate == 0)
+ REG_UPDATE(VMID_SETTINGS_0,
+ VMID, address->vmid);
+
+ if (address->type == PLN_ADDR_TYPE_GRPH_STEREO) {
+ REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0);
+ REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x1);
+
+ } else {
+ // turn off stereo if not in stereo
+ REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_MODE_FOR_STEREOSYNC, 0x0);
+ REG_UPDATE(DCSURF_FLIP_CONTROL, SURFACE_FLIP_IN_STEREOSYNC, 0x0);
+ }
+
+ /* HW automatically latch rest of address register on write to
+ * DCSURF_PRIMARY_SURFACE_ADDRESS if SURFACE_UPDATE_LOCK is not used
+ *
+ * program high first and then the low addr, order matters!
+ */
+ switch (address->type) {
+ case PLN_ADDR_TYPE_GRAPHICS:
+ /* DCN1.0 does not support const color
+ * TODO: program DCHUBBUB_RET_PATH_DCC_CFGx_0/1
+ * base on address->grph.dcc_const_color
+ * x = 0, 2, 4, 6 for pipe 0, 1, 2, 3 for rgb and luma
+ * x = 1, 3, 5, 7 for pipe 0, 1, 2, 3 for chroma
+ */
+
+ if (address->grph.addr.quad_part == 0)
+ break;
+
+ REG_UPDATE_2(DCSURF_SURFACE_CONTROL,
+ PRIMARY_SURFACE_TMZ, address->tmz_surface,
+ PRIMARY_META_SURFACE_TMZ, address->tmz_surface);
+
+ if (address->grph.meta_addr.quad_part != 0) {
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0,
+ PRIMARY_META_SURFACE_ADDRESS_HIGH,
+ address->grph.meta_addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0,
+ PRIMARY_META_SURFACE_ADDRESS,
+ address->grph.meta_addr.low_part);
+ }
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
+ PRIMARY_SURFACE_ADDRESS_HIGH,
+ address->grph.addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0,
+ PRIMARY_SURFACE_ADDRESS,
+ address->grph.addr.low_part);
+ break;
+ case PLN_ADDR_TYPE_VIDEO_PROGRESSIVE:
+ if (address->video_progressive.luma_addr.quad_part == 0
+ || address->video_progressive.chroma_addr.quad_part == 0)
+ break;
+
+ REG_UPDATE_4(DCSURF_SURFACE_CONTROL,
+ PRIMARY_SURFACE_TMZ, address->tmz_surface,
+ PRIMARY_SURFACE_TMZ_C, address->tmz_surface,
+ PRIMARY_META_SURFACE_TMZ, address->tmz_surface,
+ PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface);
+
+ if (address->video_progressive.luma_meta_addr.quad_part != 0) {
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0,
+ PRIMARY_META_SURFACE_ADDRESS_HIGH_C,
+ address->video_progressive.chroma_meta_addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0,
+ PRIMARY_META_SURFACE_ADDRESS_C,
+ address->video_progressive.chroma_meta_addr.low_part);
+
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0,
+ PRIMARY_META_SURFACE_ADDRESS_HIGH,
+ address->video_progressive.luma_meta_addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0,
+ PRIMARY_META_SURFACE_ADDRESS,
+ address->video_progressive.luma_meta_addr.low_part);
+ }
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0,
+ PRIMARY_SURFACE_ADDRESS_HIGH_C,
+ address->video_progressive.chroma_addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0,
+ PRIMARY_SURFACE_ADDRESS_C,
+ address->video_progressive.chroma_addr.low_part);
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
+ PRIMARY_SURFACE_ADDRESS_HIGH,
+ address->video_progressive.luma_addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0,
+ PRIMARY_SURFACE_ADDRESS,
+ address->video_progressive.luma_addr.low_part);
+ break;
+ case PLN_ADDR_TYPE_GRPH_STEREO:
+ if (address->grph_stereo.left_addr.quad_part == 0)
+ break;
+ if (address->grph_stereo.right_addr.quad_part == 0)
+ break;
+
+ REG_UPDATE_8(DCSURF_SURFACE_CONTROL,
+ PRIMARY_SURFACE_TMZ, address->tmz_surface,
+ PRIMARY_SURFACE_TMZ_C, address->tmz_surface,
+ PRIMARY_META_SURFACE_TMZ, address->tmz_surface,
+ PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface,
+ SECONDARY_SURFACE_TMZ, address->tmz_surface,
+ SECONDARY_SURFACE_TMZ_C, address->tmz_surface,
+ SECONDARY_META_SURFACE_TMZ, address->tmz_surface,
+ SECONDARY_META_SURFACE_TMZ_C, address->tmz_surface);
+
+ if (address->grph_stereo.right_meta_addr.quad_part != 0) {
+
+ REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH_C, 0,
+ SECONDARY_META_SURFACE_ADDRESS_HIGH_C,
+ address->grph_stereo.right_alpha_meta_addr.high_part);
+
+ REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_C, 0,
+ SECONDARY_META_SURFACE_ADDRESS_C,
+ address->grph_stereo.right_alpha_meta_addr.low_part);
+
+ REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS_HIGH, 0,
+ SECONDARY_META_SURFACE_ADDRESS_HIGH,
+ address->grph_stereo.right_meta_addr.high_part);
+
+ REG_SET(DCSURF_SECONDARY_META_SURFACE_ADDRESS, 0,
+ SECONDARY_META_SURFACE_ADDRESS,
+ address->grph_stereo.right_meta_addr.low_part);
+ }
+ if (address->grph_stereo.left_meta_addr.quad_part != 0) {
+
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0,
+ PRIMARY_META_SURFACE_ADDRESS_HIGH_C,
+ address->grph_stereo.left_alpha_meta_addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0,
+ PRIMARY_META_SURFACE_ADDRESS_C,
+ address->grph_stereo.left_alpha_meta_addr.low_part);
+
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0,
+ PRIMARY_META_SURFACE_ADDRESS_HIGH,
+ address->grph_stereo.left_meta_addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0,
+ PRIMARY_META_SURFACE_ADDRESS,
+ address->grph_stereo.left_meta_addr.low_part);
+ }
+
+ REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH_C, 0,
+ SECONDARY_SURFACE_ADDRESS_HIGH_C,
+ address->grph_stereo.right_alpha_addr.high_part);
+
+ REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_C, 0,
+ SECONDARY_SURFACE_ADDRESS_C,
+ address->grph_stereo.right_alpha_addr.low_part);
+
+ REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS_HIGH, 0,
+ SECONDARY_SURFACE_ADDRESS_HIGH,
+ address->grph_stereo.right_addr.high_part);
+
+ REG_SET(DCSURF_SECONDARY_SURFACE_ADDRESS, 0,
+ SECONDARY_SURFACE_ADDRESS,
+ address->grph_stereo.right_addr.low_part);
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0,
+ PRIMARY_SURFACE_ADDRESS_HIGH_C,
+ address->grph_stereo.left_alpha_addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0,
+ PRIMARY_SURFACE_ADDRESS_C,
+ address->grph_stereo.left_alpha_addr.low_part);
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
+ PRIMARY_SURFACE_ADDRESS_HIGH,
+ address->grph_stereo.left_addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0,
+ PRIMARY_SURFACE_ADDRESS,
+ address->grph_stereo.left_addr.low_part);
+ break;
+ case PLN_ADDR_TYPE_RGBEA:
+ if (address->rgbea.addr.quad_part == 0
+ || address->rgbea.alpha_addr.quad_part == 0)
+ break;
+
+ REG_UPDATE_4(DCSURF_SURFACE_CONTROL,
+ PRIMARY_SURFACE_TMZ, address->tmz_surface,
+ PRIMARY_SURFACE_TMZ_C, address->tmz_surface,
+ PRIMARY_META_SURFACE_TMZ, address->tmz_surface,
+ PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface);
+
+ if (address->rgbea.meta_addr.quad_part != 0) {
+
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH_C, 0,
+ PRIMARY_META_SURFACE_ADDRESS_HIGH_C,
+ address->rgbea.alpha_meta_addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_C, 0,
+ PRIMARY_META_SURFACE_ADDRESS_C,
+ address->rgbea.alpha_meta_addr.low_part);
+
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH, 0,
+ PRIMARY_META_SURFACE_ADDRESS_HIGH,
+ address->rgbea.meta_addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_META_SURFACE_ADDRESS, 0,
+ PRIMARY_META_SURFACE_ADDRESS,
+ address->rgbea.meta_addr.low_part);
+ }
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH_C, 0,
+ PRIMARY_SURFACE_ADDRESS_HIGH_C,
+ address->rgbea.alpha_addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_C, 0,
+ PRIMARY_SURFACE_ADDRESS_C,
+ address->rgbea.alpha_addr.low_part);
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH, 0,
+ PRIMARY_SURFACE_ADDRESS_HIGH,
+ address->rgbea.addr.high_part);
+
+ REG_SET(DCSURF_PRIMARY_SURFACE_ADDRESS, 0,
+ PRIMARY_SURFACE_ADDRESS,
+ address->rgbea.addr.low_part);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ break;
+ }
+
+ hubp->request_address = *address;
+
+ return true;
+}
+
+struct hubp_funcs dcn42_hubp_funcs = {
+ .hubp_enable_tripleBuffer = hubp2_enable_triplebuffer,
+ .hubp_is_triplebuffer_enabled = hubp2_is_triplebuffer_enabled,
+ .hubp_program_surface_flip_and_addr = hubp42_program_surface_flip_and_addr,
+ .hubp_program_surface_config = hubp42_program_surface_config,
+ .hubp_is_flip_pending = hubp2_is_flip_pending,
+ .hubp_setup2 = hubp42_setup,
+ .hubp_setup_interdependent2 = hubp401_setup_interdependent,
+ .hubp_set_vm_system_aperture_settings = hubp3_set_vm_system_aperture_settings,
+ .set_blank = hubp2_set_blank,
+ .set_blank_regs = hubp2_set_blank_regs,
+ .dcc_control = hubp3_dcc_control,
+ .hubp_reset = hubp_reset,
+ .mem_program_viewport = min_set_viewport,
+ .set_cursor_attributes = hubp32_cursor_set_attributes,
+ .set_cursor_position = hubp401_cursor_set_position,
+ .hubp_clk_cntl = hubp2_clk_cntl,
+ .hubp_vtg_sel = hubp2_vtg_sel,
+ .dmdata_set_attributes = hubp3_dmdata_set_attributes,
+ .dmdata_load = hubp2_dmdata_load,
+ .dmdata_status_done = hubp2_dmdata_status_done,
+ .hubp_read_state = hubp42_read_state,
+ .hubp_clear_underflow = hubp2_clear_underflow,
+ .hubp_set_flip_control_surface_gsl = hubp2_set_flip_control_surface_gsl,
+ .hubp_init = hubp42_init,
+ .set_unbounded_requesting = hubp31_set_unbounded_requesting,
+ .hubp_soft_reset = hubp31_soft_reset,
+ .hubp_set_flip_int = hubp1_set_flip_int,
+ .hubp_in_blank = hubp1_in_blank,
+ .program_extended_blank = hubp31_program_extended_blank_value,
+ .hubp_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_crossbar = hubp42_program_3dlut_fl_crossbar,
+ .hubp_get_3dlut_fl_done = hubp401_get_3dlut_fl_done,
+ .hubp_clear_tiling = hubp3_clear_tiling,
+ .hubp_program_3dlut_fl_config = hubp401_program_3dlut_fl_config,
+ .hubp_read_reg_state = hubp3_read_reg_state
+};
+
+bool hubp42_construct(
+ struct dcn20_hubp *hubp2,
+ struct dc_context *ctx,
+ uint32_t inst,
+ const struct dcn_hubp2_registers *hubp_regs,
+ const struct dcn_hubp2_shift *hubp_shift,
+ const struct dcn_hubp2_mask *hubp_mask)
+{
+ hubp2->base.funcs = &dcn42_hubp_funcs;
+ hubp2->base.ctx = ctx;
+ hubp2->hubp_regs = hubp_regs;
+ hubp2->hubp_shift = hubp_shift;
+ hubp2->hubp_mask = hubp_mask;
+ hubp2->base.inst = inst;
+ hubp2->base.opp_id = OPP_ID_INVALID;
+ hubp2->base.mpcc_id = 0xf;
+
+ return true;
+}
+
+
+void hubp42_read_state(struct hubp *hubp)
+{
+ struct dcn20_hubp *hubp2 = TO_DCN20_HUBP(hubp);
+ struct dcn_hubp_state *s = &hubp2->state;
+ struct dcn_fl_regs_st *fl_regs = &s->fl_regs;
+
+ hubp401_read_state(hubp);
+
+ /* CONTROL */
+ REG_GET_5(HUBP_3DLUT_CONTROL,
+ HUBP_3DLUT_ENABLE, &fl_regs->lut_enable,
+ HUBP_3DLUT_DONE, &fl_regs->lut_done,
+ HUBP_3DLUT_ADDRESSING_MODE, &fl_regs->lut_addr_mode,
+ HUBP_3DLUT_WIDTH, &fl_regs->lut_width,
+ HUBP_3DLUT_MPC_WIDTH, &fl_regs->lut_mpc_width);
+
+ REG_GET_4(HUBP_3DLUT_CONTROL,
+ HUBP_3DLUT_TMZ, &fl_regs->lut_tmz,
+ HUBP_3DLUT_CROSSBAR_SEL_R, &fl_regs->lut_crossbar_sel_r,
+ HUBP_3DLUT_CROSSBAR_SEL_G, &fl_regs->lut_crossbar_sel_g,
+ HUBP_3DLUT_CROSSBAR_SEL_B, &fl_regs->lut_crossbar_sel_b);
+
+ /* ADDR */
+ REG_GET(HUBP_3DLUT_ADDRESS_HIGH,
+ HUBP_3DLUT_ADDRESS_HIGH, &fl_regs->lut_addr_hi);
+ REG_GET(HUBP_3DLUT_ADDRESS_LOW,
+ HUBP_3DLUT_ADDRESS_LOW, &fl_regs->lut_addr_lo);
+ /* CLK */
+ REG_GET(HUBP_3DLUT_DLG_PARAM,
+ REFCYC_PER_3DLUT_GROUP, &fl_regs->refcyc_3dlut_group);
+ /* FL */
+ REG_GET_2(_3DLUT_FL_BIAS_SCALE,
+ HUBP0_3DLUT_FL_BIAS, &fl_regs->lut_fl_bias,
+ HUBP0_3DLUT_FL_SCALE, &fl_regs->lut_fl_scale);
+ REG_GET_2(_3DLUT_FL_CONFIG,
+ HUBP0_3DLUT_FL_MODE, &fl_regs->lut_fl_mode,
+ HUBP0_3DLUT_FL_FORMAT, &fl_regs->lut_fl_format);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h
new file mode 100644
index 000000000000..88bb1337ab9d
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/hubp/dcn42/dcn42_hubp.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_HUBP_DCN42_H__
+#define __DC_HUBP_DCN42_H__
+
+#include "dcn35/dcn35_hubp.h"
+
+#define HUBP_MASK_SH_LIST_DCN42(mask_sh)\
+ HUBP_MASK_SH_LIST_DCN35(mask_sh),\
+ HUBP_SF(HUBP0_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_MODE, mask_sh),\
+ HUBP_SF(HUBP0_3DLUT_FL_CONFIG, HUBP0_3DLUT_FL_FORMAT, mask_sh),\
+ HUBP_SF(HUBP0_3DLUT_FL_BIAS_SCALE, HUBP0_3DLUT_FL_BIAS, mask_sh),\
+ HUBP_SF(HUBP0_3DLUT_FL_BIAS_SCALE, HUBP0_3DLUT_FL_SCALE, mask_sh),\
+ HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_ENABLE, mask_sh),\
+ HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_DONE, mask_sh),\
+ HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_ADDRESSING_MODE, mask_sh),\
+ HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_WIDTH, mask_sh),\
+ HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_MPC_WIDTH, mask_sh),\
+ HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_TMZ, mask_sh),\
+ HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SEL_B, mask_sh),\
+ HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SEL_G, mask_sh),\
+ HUBP_SF(CURSOR0_0_HUBP_3DLUT_CONTROL, HUBP_3DLUT_CROSSBAR_SEL_R, mask_sh),\
+ HUBP_SF(CURSOR0_0_HUBP_3DLUT_ADDRESS_HIGH, HUBP_3DLUT_ADDRESS_HIGH, mask_sh),\
+ HUBP_SF(CURSOR0_0_HUBP_3DLUT_ADDRESS_LOW, HUBP_3DLUT_ADDRESS_LOW, mask_sh),\
+ HUBP_SF(CURSOR0_0_HUBP_3DLUT_DLG_PARAM, REFCYC_PER_3DLUT_GROUP, mask_sh)
+
+struct dml2_display_rq_regs;
+
+bool hubp42_construct(
+ struct dcn20_hubp *hubp2,
+ struct dc_context *ctx,
+ uint32_t inst,
+ const struct dcn_hubp2_registers *hubp_regs,
+ const struct dcn_hubp2_shift *hubp_shift,
+ const struct dcn_hubp2_mask *hubp_mask);
+
+void hubp42_program_3dlut_fl_crossbar(struct hubp *hubp,
+ 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);
+
+void hubp42_program_requestor(
+ struct hubp *hubp,
+ struct dml2_display_rq_regs *rq_regs);
+
+void hubp42_setup(
+ struct hubp *hubp,
+ struct dml2_dchub_per_pipe_register_set *pipe_regs,
+ union dml2_global_sync_programming *pipe_global_sync,
+ struct dc_crtc_timing *timing);
+
+#endif /* __DC_HUBP_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/Makefile b/drivers/gpu/drm/amd/display/dc/hwss/Makefile
index bee617ca0838..08cbbf87a19f 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/hwss/Makefile
@@ -1,5 +1,4 @@
-
-# Copyright 2022 Advanced Micro Devices, Inc.
+# Copyright 2022-2026 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -199,4 +198,13 @@ HWSS_DCN401 = dcn401_hwseq.o dcn401_init.o
AMD_DAL_HWSS_DCN401 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn401/,$(HWSS_DCN401))
AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN401)
+
+###############################################################################
+
+HWSS_DCN42 = dcn42_hwseq.o dcn42_init.o
+
+AMD_DAL_HWSS_DCN42 = $(addprefix $(AMDDALPATH)/dc/hwss/dcn42/,$(HWSS_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN42)
+
endif
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 f66a38f43a09..dc8feca578c5 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Advanced Micro Devices, Inc.
+ * Copyright 2016, 2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -700,6 +700,8 @@ struct dce_hwseq_registers {
uint32_t DOMAIN23_PG_STATUS;
uint32_t DOMAIN24_PG_STATUS;
uint32_t DOMAIN25_PG_STATUS;
+ uint32_t DOMAIN26_PG_CONFIG;
+ uint32_t DOMAIN26_PG_STATUS;
};
/* set field name */
#define HWS_SF(blk_name, reg_name, field_name, post_fix)\
@@ -1245,6 +1247,13 @@ struct dce_hwseq_registers {
type DOMAIN25_PGFSM_PWR_STATUS; \
type DOMAIN_DESIRED_PWR_STATE;
+#define HWSEQ_DCN42_REG_FIELD_LIST(type) \
+ type DPIASYMCLK4_GATE_DISABLE;\
+ type DPIASYMCLK5_GATE_DISABLE;\
+ type DOMAIN26_POWER_FORCEON; \
+ type DOMAIN26_POWER_GATE; \
+ type DOMAIN26_PGFSM_PWR_STATUS;
+
struct dce_hwseq_shift {
HWSEQ_REG_FIELD_LIST(uint8_t)
HWSEQ_DCN_REG_FIELD_LIST(uint8_t)
@@ -1253,6 +1262,7 @@ struct dce_hwseq_shift {
HWSEQ_DCN31_REG_FIELD_LIST(uint8_t)
HWSEQ_DCN35_REG_FIELD_LIST(uint8_t)
HWSEQ_DCN401_REG_FIELD_LIST(uint8_t)
+ HWSEQ_DCN42_REG_FIELD_LIST(uint8_t)
};
struct dce_hwseq_mask {
@@ -1263,6 +1273,7 @@ struct dce_hwseq_mask {
HWSEQ_DCN31_REG_FIELD_LIST(uint32_t)
HWSEQ_DCN35_REG_FIELD_LIST(uint32_t)
HWSEQ_DCN401_REG_FIELD_LIST(uint32_t)
+ HWSEQ_DCN42_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 699a756bbc40..5273ca09fe12 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
@@ -86,9 +86,9 @@
hws->ctx
#define DC_LOGGER \
- ctx->logger
-#define DC_LOGGER_INIT() \
- struct dc_context *ctx = dc->ctx
+ dc_ctx->logger
+#define DC_LOGGER_INIT(ctx) \
+ struct dc_context *dc_ctx = ctx
#define REG(reg)\
hws->regs->reg
@@ -201,6 +201,8 @@ static void enable_display_pipe_clock_gating(
struct dc_context *ctx,
bool clock_gating)
{
+ (void)ctx;
+ (void)clock_gating;
/*TODO*/
}
@@ -284,6 +286,7 @@ static bool
dce110_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
const struct dc_plane_state *plane_state)
{
+ (void)dc;
struct input_pixel_processor *ipp = pipe_ctx->plane_res.ipp;
const struct dc_transfer_func *tf = NULL;
struct ipp_prescale_params prescale_params = { 0 };
@@ -488,15 +491,15 @@ dce110_translate_regamma_to_hw_format(const struct dc_transfer_func *output_tf,
seg_distr[8] = 4;
seg_distr[9] = 4;
seg_distr[10] = 0;
- seg_distr[11] = -1;
- seg_distr[12] = -1;
- seg_distr[13] = -1;
- seg_distr[14] = -1;
- seg_distr[15] = -1;
+ seg_distr[11] = (uint32_t)-1;
+ seg_distr[12] = (uint32_t)-1;
+ seg_distr[13] = (uint32_t)-1;
+ seg_distr[14] = (uint32_t)-1;
+ seg_distr[15] = (uint32_t)-1;
}
for (k = 0; k < 16; k++) {
- if (seg_distr[k] != -1)
+ if (seg_distr[k] != (uint32_t)-1)
hw_points += (1 << seg_distr[k]);
}
@@ -607,6 +610,7 @@ static bool
dce110_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
const struct dc_stream_state *stream)
{
+ (void)dc;
struct transform *xfm = pipe_ctx->plane_res.xfm;
xfm->funcs->opp_power_on_regamma_lut(xfm, true);
@@ -660,6 +664,30 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx)
}
}
+static void
+dce110_dac_encoder_control(struct pipe_ctx *pipe_ctx, bool enable)
+{
+ struct dc_link *link = pipe_ctx->stream->link;
+ struct dc_bios *bios = link->ctx->dc_bios;
+ struct bp_encoder_control encoder_control = {0};
+
+ encoder_control.action = enable ? ENCODER_CONTROL_ENABLE : ENCODER_CONTROL_DISABLE;
+ encoder_control.engine_id = link->link_enc->analog_engine;
+ encoder_control.pixel_clock = pipe_ctx->stream->timing.pix_clk_100hz / 10;
+ bios->funcs->encoder_control(bios, &encoder_control);
+}
+
+static bool
+dce110_dac_load_detect(struct dc_link *link)
+{
+ struct dc_bios *bios = link->ctx->dc_bios;
+ struct link_encoder *link_enc = link->link_enc;
+ enum bp_result bp_result;
+
+ bp_result = bios->funcs->dac_load_detection(bios, link_enc->analog_engine);
+ return bp_result == BP_RESULT_OK;
+}
+
void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
{
enum dc_lane_count lane_count =
@@ -672,6 +700,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
uint32_t early_control = 0;
struct timing_generator *tg = pipe_ctx->stream_res.tg;
+ link_hwss->setup_stream_attribute(pipe_ctx);
link_hwss->setup_stream_encoder(pipe_ctx);
dc->hwss.update_info_frame(pipe_ctx);
@@ -690,6 +719,8 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
tg->funcs->set_early_control(tg, early_control);
+ if (dc_is_rgb_signal(pipe_ctx->stream->signal))
+ dce110_dac_encoder_control(pipe_ctx, true);
}
static enum bp_result link_transmitter_control(
@@ -711,13 +742,14 @@ void dce110_edp_wait_for_hpd_ready(
struct dc_link *link,
bool power_up)
{
- struct dc_context *ctx = link->ctx;
struct graphics_object_id connector = link->link_enc->connector;
bool edp_hpd_high = false;
uint32_t time_elapsed = 0;
uint32_t timeout = power_up ?
PANEL_POWER_UP_TIMEOUT : PANEL_POWER_DOWN_TIMEOUT;
+ DC_LOGGER_INIT(link->ctx);
+
if (dal_graphics_object_id_get_connector_id(connector)
!= CONNECTOR_ID_EDP) {
BREAK_TO_DEBUGGER();
@@ -769,6 +801,7 @@ void dce110_edp_power_control(
enum bp_result bp_result;
uint8_t pwrseq_instance;
+ DC_LOGGER_INIT(ctx);
if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
!= CONNECTOR_ID_EDP) {
@@ -937,6 +970,8 @@ void dce110_edp_backlight_control(
unsigned int pre_T11_delay = (link->dpcd_sink_ext_caps.bits.oled ? OLED_PRE_T11_DELAY : 0);
unsigned int post_T7_delay = (link->dpcd_sink_ext_caps.bits.oled ? OLED_POST_T7_DELAY : 0);
+ DC_LOGGER_INIT(ctx);
+
if (dal_graphics_object_id_get_connector_id(link->link_enc->connector)
!= CONNECTOR_ID_EDP) {
BREAK_TO_DEBUGGER();
@@ -1183,6 +1218,9 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst,
link_enc->transmitter - TRANSMITTER_UNIPHY_A);
}
+
+ if (dc_is_rgb_signal(pipe_ctx->stream->signal))
+ dce110_dac_encoder_control(pipe_ctx, false);
}
void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
@@ -1505,6 +1543,7 @@ static enum dc_status dce110_enable_stream_timing(
struct dc_state *context,
struct dc *dc)
{
+ (void)context;
struct dc_stream_state *stream = pipe_ctx->stream;
struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx.
pipe_ctx[pipe_ctx->pipe_idx];
@@ -1534,7 +1573,7 @@ static enum dc_status dce110_enable_stream_timing(
return DC_ERROR_UNEXPECTED;
}
- if (dc_is_hdmi_tmds_signal(stream->signal)) {
+ if (dc_is_tmds_signal(stream->signal)) {
stream->link->phy_state.symclk_ref_cnts.otg = 1;
if (stream->link->phy_state.symclk_state == SYMCLK_OFF_TX_OFF)
stream->link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
@@ -1564,6 +1603,22 @@ static enum dc_status dce110_enable_stream_timing(
return DC_OK;
}
+static void
+dce110_select_crtc_source(struct pipe_ctx *pipe_ctx)
+{
+ struct dc_link *link = pipe_ctx->stream->link;
+ struct dc_bios *bios = link->ctx->dc_bios;
+ struct bp_crtc_source_select crtc_source_select = {0};
+ enum engine_id engine_id = link->link_enc->preferred_engine;
+
+ if (dc_is_rgb_signal(pipe_ctx->stream->signal))
+ engine_id = link->link_enc->analog_engine;
+ crtc_source_select.controller_id = CONTROLLER_ID_D0 + pipe_ctx->stream_res.tg->inst;
+ crtc_source_select.color_depth = pipe_ctx->stream->timing.display_color_depth;
+ crtc_source_select.engine_id = engine_id;
+ crtc_source_select.sink_signal = pipe_ctx->stream->signal;
+ bios->funcs->select_crtc_source(bios, &crtc_source_select);
+}
enum dc_status dce110_apply_single_controller_ctx_to_hw(
struct pipe_ctx *pipe_ctx,
@@ -1584,6 +1639,10 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw(
hws->funcs.disable_stream_gating(dc, pipe_ctx);
}
+ if (pipe_ctx->stream->signal == SIGNAL_TYPE_RGB) {
+ dce110_select_crtc_source(pipe_ctx);
+ }
+
if (pipe_ctx->stream_res.audio != NULL) {
struct audio_output audio_output = {0};
@@ -1663,7 +1722,8 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw(
pipe_ctx->stream_res.tg->funcs->set_static_screen_control(
pipe_ctx->stream_res.tg, event_triggers, 2);
- if (!dc_is_virtual_signal(pipe_ctx->stream->signal))
+ if (!dc_is_virtual_signal(pipe_ctx->stream->signal) &&
+ !dc_is_rgb_signal(pipe_ctx->stream->signal))
pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg(
pipe_ctx->stream_res.stream_enc,
pipe_ctx->stream_res.tg->inst);
@@ -1885,6 +1945,35 @@ static void clean_up_dsc_blocks(struct dc *dc)
}
}
+static void dc_hwss_enable_otg_pwa(
+ struct dc *dc,
+ struct pipe_ctx *pipe_ctx)
+{
+ struct timing_generator *tg = NULL;
+
+ if (dc->debug.enable_otg_frame_sync_pwa == 0)
+ return;
+
+ if (pipe_ctx == NULL || pipe_ctx->stream_res.tg == NULL)
+ return;
+ tg = pipe_ctx->stream_res.tg;
+
+ /*only enable this if one active*/
+ if (tg->funcs->enable_otg_pwa) {
+ struct otc_pwa_frame_sync pwa_param = {0};
+
+ DC_LOGGER_INIT(dc->ctx);
+ /* mode 1 to choose generate pwa sync signal on line 0 counting
+ * from vstartup at very beginning of the frame
+ */
+ pwa_param.pwa_frame_sync_line_offset = 0;
+ pwa_param.pwa_sync_mode = DC_OTG_PWA_FRAME_SYNC_MODE_VSTARTUP;
+ /*frame sync line for generating high frame sync*/
+ tg->funcs->enable_otg_pwa(tg, &pwa_param);
+ DC_LOG_DC("Enable OTG PWA frame sync on TG %d\n", tg->inst);
+ }
+}
+
/*
* When ASIC goes from VBIOS/VGA mode to driver/accelerated mode we need:
* 1. Power down all DC HW blocks
@@ -1902,7 +1991,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
struct pipe_ctx *pipe_ctx = NULL;
struct dce_hwseq *hws = dc->hwseq;
int edp_with_sink_num;
- int edp_num;
+ unsigned int edp_num;
int edp_stream_num;
int i;
bool can_apply_edp_fast_boot = false;
@@ -1910,8 +1999,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
bool keep_edp_vdd_on = false;
bool should_clean_dsc_block = true;
struct dc_bios *dcb = dc->ctx->dc_bios;
- DC_LOGGER_INIT();
-
+ DC_LOGGER_INIT(dc->ctx);
get_edp_links_with_sink(dc, edp_links_with_sink, &edp_with_sink_num);
dc_get_edp_links(dc, edp_links, &edp_num);
@@ -1962,6 +2050,7 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
// If VBios supports it, we check it from reigster or other flags.
pipe_ctx->stream_res.pix_clk_params.dio_se_pix_per_cycle = 1;
}
+ dc_hwss_enable_otg_pwa(dc, pipe_ctx);
}
break;
}
@@ -2334,7 +2423,7 @@ static void dce110_reset_hw_ctx_wrap(
BREAK_TO_DEBUGGER();
}
pipe_ctx_old->stream_res.tg->funcs->disable_crtc(pipe_ctx_old->stream_res.tg);
- if (dc_is_hdmi_tmds_signal(pipe_ctx_old->stream->signal))
+ if (dc_is_tmds_signal(pipe_ctx_old->stream->signal))
pipe_ctx_old->stream->link->phy_state.symclk_ref_cnts.otg = 0;
pipe_ctx_old->plane_res.mi->funcs->free_mem_input(
pipe_ctx_old->plane_res.mi, dc->current_state->stream_count);
@@ -2531,6 +2620,18 @@ enum dc_status dce110_apply_ctx_to_hw(
#endif
}
+
+ if (dc->debug.enable_otg_frame_sync_pwa && context->stream_count == 1) {
+ /* only enable this on one OTG*/
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+ if (pipe_ctx && pipe_ctx->stream != NULL) {
+ dc_hwss_enable_otg_pwa(dc, pipe_ctx);
+ break;
+ }
+ }
+ }
if (dc->fbc_compressor)
enable_fbc(dc, dc->current_state);
@@ -2632,6 +2733,7 @@ static void program_gamut_remap(struct pipe_ctx *pipe_ctx)
static void update_plane_addr(const struct dc *dc,
struct pipe_ctx *pipe_ctx)
{
+ (void)dc;
struct dc_plane_state *plane_state = pipe_ctx->plane_state;
if (plane_state == NULL)
@@ -2677,7 +2779,6 @@ static bool wait_for_reset_trigger_to_occur(
struct dc_context *dc_ctx,
struct timing_generator *tg)
{
- struct dc_context *ctx = dc_ctx;
bool rc = false;
/* To avoid endless loop we wait at most
@@ -2719,10 +2820,11 @@ static void dce110_enable_timing_synchronization(
int group_size,
struct pipe_ctx *grouped_pipes[])
{
- struct dc_context *dc_ctx = dc->ctx;
+ (void)state;
+ (void)group_index;
struct dcp_gsl_params gsl_params = { 0 };
int i;
- DC_LOGGER_INIT();
+ DC_LOGGER_INIT(dc->ctx);
DC_SYNC_INFO("GSL: Setting-up...\n");
@@ -2765,10 +2867,9 @@ static void dce110_enable_per_frame_crtc_position_reset(
int group_size,
struct pipe_ctx *grouped_pipes[])
{
- struct dc_context *dc_ctx = dc->ctx;
struct dcp_gsl_params gsl_params = { 0 };
int i;
- DC_LOGGER_INIT();
+ DC_LOGGER_INIT(dc->ctx);
gsl_params.gsl_group = 0;
gsl_params.gsl_master = 0;
@@ -2796,6 +2897,8 @@ static void dce110_enable_per_frame_crtc_position_reset(
static void dce110_init_pipes(struct dc *dc, struct dc_state *context)
{
+ (void)context;
+ (void)dc;
// Do nothing
}
@@ -3061,10 +3164,13 @@ static void dce110_post_unlock_program_front_end(
struct dc *dc,
struct dc_state *context)
{
+ (void)dc;
+ (void)context;
}
static void dce110_power_down_fe(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx)
{
+ (void)state;
struct dce_hwseq *hws = dc->hwseq;
int fe_idx = pipe_ctx->plane_res.mi ?
pipe_ctx->plane_res.mi->inst : pipe_ctx->pipe_idx;
@@ -3085,6 +3191,9 @@ static void dce110_wait_for_mpcc_disconnect(
struct resource_pool *res_pool,
struct pipe_ctx *pipe_ctx)
{
+ (void)dc;
+ (void)res_pool;
+ (void)pipe_ctx;
/* do nothing*/
}
@@ -3094,6 +3203,10 @@ static void program_output_csc(struct dc *dc,
uint16_t *matrix,
int opp_id)
{
+ (void)dc;
+ (void)colorspace;
+ (void)matrix;
+ (void)opp_id;
int i;
struct out_csc_color_matrix tbl_entry;
@@ -3238,6 +3351,7 @@ void dce110_enable_lvds_link_output(struct dc_link *link,
enum clock_source_id clock_source,
uint32_t pixel_clock)
{
+ (void)link_res;
link->link_enc->funcs->enable_lvds_output(
link->link_enc,
clock_source,
@@ -3252,6 +3366,7 @@ void dce110_enable_tmds_link_output(struct dc_link *link,
enum dc_color_depth color_depth,
uint32_t pixel_clock)
{
+ (void)link_res;
link->link_enc->funcs->enable_tmds_output(
link->link_enc,
clock_source,
@@ -3261,15 +3376,6 @@ void dce110_enable_tmds_link_output(struct dc_link *link,
link->phy_state.symclk_state = SYMCLK_ON_TX_ON;
}
-static void dce110_enable_analog_link_output(
- struct dc_link *link,
- uint32_t pix_clk_100hz)
-{
- link->link_enc->funcs->enable_analog_output(
- link->link_enc,
- pix_clk_100hz);
-}
-
void dce110_enable_dp_link_output(
struct dc_link *link,
const struct link_resource *link_res,
@@ -3407,8 +3513,8 @@ static const struct hw_sequencer_funcs dce110_funcs = {
.enable_lvds_link_output = dce110_enable_lvds_link_output,
.enable_tmds_link_output = dce110_enable_tmds_link_output,
.enable_dp_link_output = dce110_enable_dp_link_output,
- .enable_analog_link_output = dce110_enable_analog_link_output,
.disable_link_output = dce110_disable_link_output,
+ .dac_load_detect = dce110_dac_load_detect,
};
static const struct hwseq_private_funcs dce110_private_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c
index 2a62f63d0357..0689bbf12ad8 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dce120/dce120_hwseq.c
@@ -154,6 +154,10 @@ static bool dce120_enable_display_power_gating(
struct dc_bios *dcb,
enum pipe_gating_control power_gating)
{
+ (void)dc;
+ (void)controller_id;
+ (void)dcb;
+ (void)power_gating;
/* disable for bringup */
#if 0
enum bp_result bp_result = BP_RESULT_OK;
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 a2d28be480e8..756ce8379538 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
@@ -60,9 +60,9 @@
#include "dc_state_priv.h"
#define DC_LOGGER \
- dc_logger
-#define DC_LOGGER_INIT(logger) \
- struct dal_logger *dc_logger = logger
+ dc_ctx->logger
+#define DC_LOGGER_INIT(ctx) \
+ struct dc_context *dc_ctx = ctx
#define CTX \
hws->ctx
@@ -86,6 +86,7 @@ static void print_microsec(struct dc_context *dc_ctx,
struct dc_log_buffer_ctx *log_ctx,
uint32_t ref_cycle)
{
+ (void)log_ctx;
const uint32_t ref_clk_mhz = dc_ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
static const unsigned int frac = 1000;
uint32_t us_x10 = (ref_cycle * frac) / ref_clk_mhz;
@@ -252,6 +253,7 @@ void dcn10_lock_all_pipes(struct dc *dc,
static void log_mpc_crc(struct dc *dc,
struct dc_log_buffer_ctx *log_ctx)
{
+ (void)log_ctx;
struct dc_context *dc_ctx = dc->ctx;
struct dce_hwseq *hws = dc->hwseq;
@@ -450,6 +452,7 @@ static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx)
static void dcn10_log_color_state(struct dc *dc,
struct dc_log_buffer_ctx *log_ctx)
{
+ (void)log_ctx;
struct dc_context *dc_ctx = dc->ctx;
struct resource_pool *pool = dc->res_pool;
bool is_gamut_remap_available = false;
@@ -813,6 +816,7 @@ void dcn10_log_hw_state(struct dc *dc,
bool dcn10_did_underflow_occur(struct dc *dc, struct pipe_ctx *pipe_ctx)
{
+ (void)dc;
struct hubp *hubp = pipe_ctx->plane_res.hubp;
struct timing_generator *tg = pipe_ctx->stream_res.tg;
@@ -1009,7 +1013,7 @@ static void power_on_plane_resources(
struct dce_hwseq *hws,
int plane_id)
{
- DC_LOGGER_INIT(hws->ctx->logger);
+ DC_LOGGER_INIT(hws->ctx);
if (hws->funcs.dpp_root_clock_control)
hws->funcs.dpp_root_clock_control(hws, plane_id, true);
@@ -1181,6 +1185,7 @@ enum dc_status dcn10_enable_stream_timing(
struct dc_state *context,
struct dc *dc)
{
+ (void)context;
struct dc_stream_state *stream = pipe_ctx->stream;
enum dc_color_space color_space;
struct tg_color black_color = {0};
@@ -1284,9 +1289,10 @@ static void dcn10_reset_back_end_for_pipe(
struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
int i;
struct dc_link *link;
- DC_LOGGER_INIT(dc->ctx->logger);
+ DC_LOGGER_INIT(dc->ctx);
if (pipe_ctx->stream_res.stream_enc == NULL) {
pipe_ctx->stream = NULL;
return;
@@ -1422,12 +1428,10 @@ void dcn10_verify_allow_pstate_change_high(struct dc *dc)
return;
if (!hubbub->funcs->verify_allow_pstate_change_high(hubbub)) {
- int i = 0;
-
if (should_log_hw_state)
dcn10_log_hw_state(dc, NULL);
- TRACE_DC_PIPE_STATE(pipe_ctx, i, MAX_PIPES);
+ TRACE_DC_PIPE_STATE(pipe_ctx, MAX_PIPES);
BREAK_TO_DEBUGGER();
if (dcn10_hw_wa_force_recovery(dc)) {
/*check again*/
@@ -1490,7 +1494,7 @@ void dcn10_plane_atomic_power_down(struct dc *dc,
struct hubp *hubp)
{
struct dce_hwseq *hws = dc->hwseq;
- DC_LOGGER_INIT(dc->ctx->logger);
+ DC_LOGGER_INIT(dc->ctx);
if (REG(DC_IP_REQUEST_CNTL)) {
REG_SET(DC_IP_REQUEST_CNTL, 0,
@@ -1553,8 +1557,9 @@ void dcn10_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
void dcn10_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx *pipe_ctx)
{
+ (void)state;
struct dce_hwseq *hws = dc->hwseq;
- DC_LOGGER_INIT(dc->ctx->logger);
+ DC_LOGGER_INIT(dc->ctx);
if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
return;
@@ -1906,7 +1911,7 @@ void dcn10_power_down_on_boot(struct dc *dc)
{
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link = NULL;
- int edp_num;
+ unsigned int edp_num;
int i = 0;
dc_get_edp_links(dc, edp_links, &edp_num);
@@ -2006,6 +2011,7 @@ static bool patch_address_for_sbs_tb_stereo(
void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
{
+ (void)dc;
bool addr_patched = false;
PHYSICAL_ADDRESS_LOC addr;
struct dc_plane_state *plane_state = pipe_ctx->plane_state;
@@ -2032,6 +2038,7 @@ void dcn10_update_plane_addr(const struct dc *dc, struct pipe_ctx *pipe_ctx)
bool dcn10_set_input_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
const struct dc_plane_state *plane_state)
{
+ (void)dc;
struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
const struct dc_transfer_func *tf = NULL;
bool result = true;
@@ -2268,8 +2275,6 @@ static bool wait_for_reset_trigger_to_occur(
{
bool rc = false;
- DC_LOGGER_INIT(dc_ctx->logger);
-
/* To avoid endless loop we wait at most
* frames_to_wait_on_triggered_reset frames for the reset to occur. */
const uint32_t frames_to_wait_on_triggered_reset = 10;
@@ -2384,7 +2389,6 @@ static uint8_t get_clock_divider(struct pipe_ctx *pipe,
static int dcn10_align_pixel_clocks(struct dc *dc, int group_size,
struct pipe_ctx *grouped_pipes[])
{
- struct dc_context *dc_ctx = dc->ctx;
int i, master = -1, embedded = -1;
struct dc_crtc_timing *hw_crtc_timing;
uint64_t phase[MAX_PIPES];
@@ -2397,7 +2401,7 @@ static int dcn10_align_pixel_clocks(struct dc *dc, int group_size,
uint32_t dp_ref_clk_100hz =
dc->res_pool->dp_clock_source->ctx->dc->clk_mgr->dprefclk_khz*10;
- DC_LOGGER_INIT(dc_ctx->logger);
+ DC_LOGGER_INIT(dc->ctx);
hw_crtc_timing = kzalloc_objs(*hw_crtc_timing, MAX_PIPES);
if (!hw_crtc_timing)
@@ -2477,12 +2481,12 @@ void dcn10_enable_vblanks_synchronization(
int group_size,
struct pipe_ctx *grouped_pipes[])
{
- struct dc_context *dc_ctx = dc->ctx;
+ (void)group_index;
struct output_pixel_processor *opp;
struct timing_generator *tg;
int i, width = 0, height = 0, master;
- DC_LOGGER_INIT(dc_ctx->logger);
+ DC_LOGGER_INIT(dc->ctx);
for (i = 1; i < group_size; i++) {
opp = grouped_pipes[i]->stream_res.opp;
@@ -2543,12 +2547,12 @@ void dcn10_enable_timing_synchronization(
int group_size,
struct pipe_ctx *grouped_pipes[])
{
- struct dc_context *dc_ctx = dc->ctx;
+ (void)group_index;
struct output_pixel_processor *opp;
struct timing_generator *tg;
int i, width = 0, height = 0;
- DC_LOGGER_INIT(dc_ctx->logger);
+ DC_LOGGER_INIT(dc->ctx);
DC_SYNC_INFO("Setting up OTG reset trigger\n");
@@ -2624,10 +2628,9 @@ void dcn10_enable_per_frame_crtc_position_reset(
int group_size,
struct pipe_ctx *grouped_pipes[])
{
- struct dc_context *dc_ctx = dc->ctx;
int i;
- DC_LOGGER_INIT(dc_ctx->logger);
+ DC_LOGGER_INIT(dc->ctx);
DC_SYNC_INFO("Setting up\n");
for (i = 0; i < group_size; i++)
@@ -2649,6 +2652,7 @@ static void mmhub_read_vm_system_aperture_settings(struct dcn10_hubp *hubp1,
struct vm_system_aperture_param *apt,
struct dce_hwseq *hws)
{
+ (void)hubp1;
PHYSICAL_ADDRESS_LOC physical_page_number;
uint32_t logical_addr_low;
uint32_t logical_addr_high;
@@ -2674,6 +2678,7 @@ static void mmhub_read_vm_context0_settings(struct dcn10_hubp *hubp1,
struct vm_context0_param *vm0,
struct dce_hwseq *hws)
{
+ (void)hubp1;
PHYSICAL_ADDRESS_LOC fb_base;
PHYSICAL_ADDRESS_LOC fb_offset;
uint32_t fb_base_value;
@@ -2732,6 +2737,7 @@ static void dcn10_enable_plane(
struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
struct dce_hwseq *hws = dc->hwseq;
if (dc->debug.sanity_checks) {
@@ -2829,6 +2835,8 @@ void dcn10_program_output_csc(struct dc *dc,
uint16_t *matrix,
int opp_id)
{
+ (void)dc;
+ (void)opp_id;
if (pipe_ctx->stream->csc_color_matrix.enable_adjustment == true) {
if (pipe_ctx->plane_res.dpp->funcs->dpp_set_csc_adjustment != NULL) {
@@ -3594,6 +3602,10 @@ bool dcn10_dummy_display_power_gating(
struct dc_bios *dcb,
enum pipe_gating_control power_gating)
{
+ (void)dc;
+ (void)controller_id;
+ (void)dcb;
+ (void)power_gating;
return true;
}
@@ -4060,6 +4072,7 @@ enum dc_status dcn10_set_clock(struct dc *dc,
uint32_t clk_khz,
uint32_t stepping)
{
+ (void)stepping;
struct dc_state *context = dc->current_state;
struct dc_clock_config clock_cfg = {0};
struct dc_clocks *current_clocks = &context->bw_ctx.bw.dcn.clk;
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 307e8f8060e6..288e4edaa9a2 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
@@ -75,6 +75,7 @@
void dcn20_log_color_state(struct dc *dc,
struct dc_log_buffer_ctx *log_ctx)
{
+ (void)log_ctx;
struct dc_context *dc_ctx = dc->ctx;
struct resource_pool *pool = dc->res_pool;
bool is_gamut_remap_available = false;
@@ -379,6 +380,7 @@ void dcn20_program_triple_buffer(
struct pipe_ctx *pipe_ctx,
bool enable_triple_buffer)
{
+ (void)dc;
if (pipe_ctx->plane_res.hubp && pipe_ctx->plane_res.hubp->funcs) {
pipe_ctx->plane_res.hubp->funcs->hubp_enable_tripleBuffer(
pipe_ctx->plane_res.hubp,
@@ -893,7 +895,7 @@ enum dc_status dcn20_enable_stream_timing(
dccg->funcs->set_dtbclk_dto(dccg, &dto_params);
}
- if (dc_is_hdmi_tmds_signal(stream->signal)) {
+ if (dc_is_tmds_signal(stream->signal)) {
stream->link->phy_state.symclk_ref_cnts.otg = 1;
if (stream->link->phy_state.symclk_state == SYMCLK_OFF_TX_OFF)
stream->link->phy_state.symclk_state = SYMCLK_ON_TX_OFF;
@@ -1175,6 +1177,8 @@ bool dcn20_set_input_transfer_func(struct dc *dc,
void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
{
+ (void)context;
+ (void)dc;
struct pipe_ctx *odm_pipe;
int opp_cnt = 1;
int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
@@ -1297,6 +1301,7 @@ static void dcn20_power_on_plane_resources(
void dcn20_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
//if (dc->debug.sanity_checks) {
// dcn10_verify_allow_pstate_change_high(dc);
//}
@@ -2652,6 +2657,7 @@ void dcn20_init_vm_ctx(
struct dc_virtual_addr_space_config *va_config,
int vmid)
{
+ (void)hws;
struct dcn_hubbub_virt_addr_config config;
if (vmid == 0) {
@@ -2670,6 +2676,7 @@ void dcn20_init_vm_ctx(
int dcn20_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config)
{
+ (void)hws;
struct dcn_hubbub_phys_addr_config config;
config.system_aperture.fb_top = pa_config->system_aperture.fb_top;
@@ -2799,6 +2806,7 @@ void dcn20_reset_back_end_for_pipe(
struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
struct dc_link *link = pipe_ctx->stream->link;
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
struct dccg *dccg = dc->res_pool->dccg;
@@ -2856,7 +2864,7 @@ void dcn20_reset_back_end_for_pipe(
* the case where the same symclk is shared across multiple otg
* instances
*/
- if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
+ if (dc_is_tmds_signal(pipe_ctx->stream->signal))
link->phy_state.symclk_ref_cnts.otg = 0;
if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) {
link_hwss->disable_link_output(link,
@@ -3245,6 +3253,7 @@ void dcn20_set_disp_pattern_generator(const struct dc *dc,
const struct tg_color *solid_color,
int width, int height, int offset)
{
+ (void)dc;
pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern,
color_space, color_depth, solid_color, width, height, offset);
}
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 d04cfd403b7e..2aa0f1de8103 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
@@ -75,6 +75,7 @@
void dcn30_log_color_state(struct dc *dc,
struct dc_log_buffer_ctx *log_ctx)
{
+ (void)log_ctx;
struct dc_context *dc_ctx = dc->ctx;
struct resource_pool *pool = dc->res_pool;
bool is_gamut_remap_available = false;
@@ -645,7 +646,7 @@ void dcn30_init_hw(struct dc *dc)
struct dc_bios *dcb = dc->ctx->dc_bios;
struct resource_pool *res_pool = dc->res_pool;
int i;
- int edp_num;
+ unsigned int edp_num;
uint32_t backlight = MAX_BACKLIGHT_LEVEL;
uint32_t user_level = MAX_BACKLIGHT_LEVEL;
@@ -1183,6 +1184,7 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc,
const struct tg_color *solid_color,
int width, int height, int offset)
{
+ (void)dc;
pipe_ctx->stream_res.opp->funcs->opp_set_disp_pattern_generator(pipe_ctx->stream_res.opp, test_pattern,
color_space, color_depth, solid_color, width, height, offset);
}
@@ -1237,6 +1239,7 @@ void dcn30_get_underflow_debug_data(const struct dc *dc,
struct timing_generator *tg,
struct dc_underflow_debug_data *out_data)
{
+ (void)tg;
struct hubbub *hubbub = dc->res_pool->hubbub;
if (hubbub) {
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c
index 3bc56ac346f3..6e1877a8682d 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn303/dcn303_hwseq.c
@@ -45,20 +45,31 @@
void dcn303_dpp_pg_control(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on)
{
+ (void)dpp_inst;
+ (void)hws;
+ (void)power_on;
/*DCN303 removes PG registers*/
}
void dcn303_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on)
{
+ (void)hubp_inst;
+ (void)hws;
+ (void)power_on;
/*DCN303 removes PG registers*/
}
void dcn303_dsc_pg_control(struct dce_hwseq *hws, unsigned int dsc_inst, bool power_on)
{
+ (void)dsc_inst;
+ (void)hws;
+ (void)power_on;
/*DCN303 removes PG registers*/
}
void dcn303_enable_power_gating_plane(struct dce_hwseq *hws, bool enable)
{
+ (void)enable;
+ (void)hws;
/*DCN303 removes PG registers*/
}
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 db2f7cbb12ff..b4afb2bc4493 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
@@ -484,6 +484,7 @@ void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool p
int dcn31_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config)
{
+ (void)hws;
struct dcn_hubbub_phys_addr_config config = {0};
config.system_aperture.fb_top = pa_config->system_aperture.fb_top;
@@ -511,9 +512,9 @@ static void dcn31_reset_back_end_for_pipe(
struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
struct dc_link *link;
- DC_LOGGER_INIT(dc->ctx->logger);
if (pipe_ctx->stream_res.stream_enc == NULL) {
pipe_ctx->stream = NULL;
return;
@@ -549,7 +550,7 @@ static void dcn31_reset_back_end_for_pipe(
* the case where the same symclk is shared across multiple otg
* instances
*/
- if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
+ if (dc_is_tmds_signal(pipe_ctx->stream->signal))
link->phy_state.symclk_ref_cnts.otg = 0;
if (pipe_ctx->top_pipe == NULL) {
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
index 3e239124c17d..858a06b03b57 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
@@ -172,6 +172,7 @@ static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_
void dcn314_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
{
+ (void)context;
struct pipe_ctx *odm_pipe;
int opp_cnt = 0;
int opp_inst[MAX_PIPES] = {0};
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 a0aaa727e9fa..b45ceb570a5c 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
@@ -570,6 +570,7 @@ bool dcn32_set_output_transfer_func(struct dc *dc,
struct pipe_ctx *pipe_ctx,
const struct dc_stream_state *stream)
{
+ (void)dc;
int mpcc_id = pipe_ctx->plane_res.hubp->inst;
struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
const struct pwl_params *params = NULL;
@@ -757,6 +758,9 @@ static void dcn32_initialize_min_clocks(struct dc *dc)
{
struct dc_clocks *clocks = &dc->current_state->bw_ctx.bw.dcn.clk;
+ if (!dc->clk_mgr || !dc->clk_mgr->bw_params || !dc->clk_mgr->funcs)
+ return;
+
clocks->dcfclk_deep_sleep_khz = DCN3_2_DCFCLK_DS_INIT_KHZ;
clocks->dcfclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz * 1000;
clocks->socclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].socclk_mhz * 1000;
@@ -765,9 +769,10 @@ static void dcn32_initialize_min_clocks(struct dc *dc)
clocks->ref_dtbclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dtbclk_mhz * 1000;
clocks->fclk_p_state_change_support = true;
clocks->p_state_change_support = true;
+
if (dc->debug.disable_boot_optimizations) {
clocks->dispclk_khz = dc->clk_mgr->bw_params->clk_table.entries[0].dispclk_mhz * 1000;
- } else {
+ } else if (dc->clk_mgr->funcs->get_dispclk_from_dentist) {
/* Even though DPG_EN = 1 for the connected display, it still requires the
* correct timing so we cannot set DISPCLK to min freq or it could cause
* audio corruption. Read current DISPCLK from DENTIST and request the same
@@ -776,10 +781,10 @@ static void dcn32_initialize_min_clocks(struct dc *dc)
clocks->dispclk_khz = dc->clk_mgr->funcs->get_dispclk_from_dentist(dc->clk_mgr);
}
- dc->clk_mgr->funcs->update_clocks(
- dc->clk_mgr,
- dc->current_state,
- true);
+ if (dc->clk_mgr->funcs->update_clocks)
+ dc->clk_mgr->funcs->update_clocks(dc->clk_mgr,
+ dc->current_state,
+ true);
}
void dcn32_init_hw(struct dc *dc)
@@ -789,7 +794,7 @@ void dcn32_init_hw(struct dc *dc)
struct dc_bios *dcb = dc->ctx->dc_bios;
struct resource_pool *res_pool = dc->res_pool;
int i;
- int edp_num;
+ unsigned int edp_num;
uint32_t backlight = MAX_BACKLIGHT_LEVEL;
uint32_t user_level = MAX_BACKLIGHT_LEVEL;
@@ -1007,7 +1012,8 @@ void dcn32_init_hw(struct dc *dc)
DMUB_FW_VERSION(7, 0, 35)) {
/* FAMS2 is disabled */
dc->debug.fams2_config.bits.enable = false;
- if (dc->debug.using_dml2 && dc->res_pool->funcs->update_bw_bounding_box) {
+ if (dc->debug.using_dml2 && dc->res_pool->funcs->update_bw_bounding_box &&
+ dc->clk_mgr && dc->clk_mgr->bw_params) {
/* update bounding box if FAMS2 disabled */
dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
}
@@ -1138,6 +1144,7 @@ static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_
void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
{
+ (void)context;
struct pipe_ctx *odm_pipe;
int opp_cnt = 0;
int opp_inst[MAX_PIPES] = {0};
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 b5a4cefbd35f..f133b52ea958 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
@@ -60,15 +60,15 @@
#include "dcn20/dcn20_hwseq.h"
#include "dc_state_priv.h"
-#define DC_LOGGER_INIT(logger) \
- struct dal_logger *dc_logger = logger
+#define DC_LOGGER \
+ dc_ctx->logger
+#define DC_LOGGER_INIT(ctx) \
+ struct dc_context *dc_ctx = ctx
#define CTX \
hws->ctx
#define REG(reg)\
hws->regs->reg
-#define DC_LOGGER \
- dc_logger
#undef FN
@@ -331,7 +331,7 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
struct pipe_ctx *odm_pipe;
int opp_cnt = 1;
- DC_LOGGER_INIT(stream->ctx->logger);
+ DC_LOGGER_INIT(stream->ctx);
ASSERT(dsc);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
@@ -428,6 +428,7 @@ static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_
void dcn35_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
{
+ (void)context;
struct pipe_ctx *odm_pipe;
int opp_cnt = 0;
int opp_inst[MAX_PIPES] = {0};
@@ -520,7 +521,7 @@ void dcn35_power_down_on_boot(struct dc *dc)
{
struct dc_link *edp_links[MAX_NUM_EDP];
struct dc_link *edp_link = NULL;
- int edp_num;
+ unsigned int edp_num;
int i = 0;
dc_get_edp_links(dc, edp_links, &edp_num);
@@ -816,6 +817,7 @@ void dcn35_init_pipes(struct dc *dc, struct dc_state *context)
void dcn35_enable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
struct dpp *dpp = pipe_ctx->plane_res.dpp;
/* enable DCFCLK current DCHUB */
@@ -897,7 +899,7 @@ void dcn35_disable_plane(struct dc *dc, struct dc_state *state, struct pipe_ctx
bool is_phantom = dc_state_get_pipe_subvp_type(state, pipe_ctx) == SUBVP_PHANTOM;
struct timing_generator *tg = is_phantom ? pipe_ctx->stream_res.tg : NULL;
- DC_LOGGER_INIT(dc->ctx->logger);
+ DC_LOGGER_INIT(dc->ctx);
if (!pipe_ctx->plane_res.hubp || pipe_ctx->plane_res.hubp->power_gated)
return;
@@ -921,7 +923,7 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,
bool hpo_frl_stream_enc_acquired = false;
bool hpo_dp_stream_enc_acquired = false;
int i = 0, j = 0;
- int edp_num = 0;
+ unsigned int edp_num = 0;
struct dc_link *edp_links[MAX_NUM_EDP] = { NULL };
memset(update_state, 0, sizeof(struct pg_block_update));
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 4dfb6c865831..9768b8f6b6fb 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
@@ -95,10 +95,6 @@ void dcn401_program_gamut_remap(struct pipe_ctx *pipe_ctx)
unsigned int mpcc_id = pipe_ctx->plane_res.mpcc_inst;
struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
- //For now assert if location is not pre-blend
- if (pipe_ctx->plane_state)
- ASSERT(pipe_ctx->plane_state->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;
@@ -144,7 +140,7 @@ void dcn401_init_hw(struct dc *dc)
struct dc_bios *dcb = dc->ctx->dc_bios;
struct resource_pool *res_pool = dc->res_pool;
int i;
- int edp_num;
+ unsigned int edp_num;
uint32_t backlight = MAX_BACKLIGHT_LEVEL;
uint32_t user_level = MAX_BACKLIGHT_LEVEL;
bool dchub_ref_freq_changed;
@@ -305,6 +301,7 @@ void dcn401_init_hw(struct dc *dc)
}
}
}
+
for (i = 0; i < res_pool->audio_count; i++) {
struct audio *audio = res_pool->audios[i];
@@ -377,293 +374,180 @@ 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 dc *dc, struct pipe_ctx *pipe_ctx)
{
- enum dc_cm2_shaper_3dlut_setting shaper_3dlut_setting = DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL;
- bool lut1d_enable = false;
- struct mpc *mpc = dc->res_pool->mpc;
- int mpcc_id = pipe_ctx->plane_res.hubp->inst;
-
- if (!pipe_ctx->plane_state)
- return;
- shaper_3dlut_setting = pipe_ctx->plane_state->mcm_shaper_3dlut_setting;
- lut1d_enable = pipe_ctx->plane_state->mcm_lut1d_enable;
- mpc->funcs->set_movable_cm_location(mpc, MPCC_MOVABLE_CM_LOCATION_BEFORE, mpcc_id);
- pipe_ctx->plane_state->mcm_location = MPCC_MOVABLE_CM_LOCATION_BEFORE;
-
- *lut1d_xable = lut1d_enable ? MCM_LUT_ENABLE : MCM_LUT_DISABLE;
+ (void)dc;
+ struct hubp *hubp = pipe_ctx->plane_res.hubp;
- switch (shaper_3dlut_setting) {
- case DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL:
- *lut3d_xable = *shaper_xable = MCM_LUT_DISABLE;
- break;
- case DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER:
- *lut3d_xable = MCM_LUT_DISABLE;
- *shaper_xable = MCM_LUT_ENABLE;
- break;
- case DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT:
- *lut3d_xable = *shaper_xable = MCM_LUT_ENABLE;
- break;
+ if (hubp->funcs->hubp_enable_3dlut_fl) {
+ hubp->funcs->hubp_enable_3dlut_fl(hubp, true);
}
}
-void dcn401_populate_mcm_luts(struct dc *dc,
- struct pipe_ctx *pipe_ctx,
- struct dc_cm2_func_luts mcm_luts,
- 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;
struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
struct hubp *hubp = pipe_ctx->plane_res.hubp;
+ 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;
- enum dc_cm2_transfer_func_source lut3d_src = mcm_luts.lut3d_data.lut3d_src;
- enum hubp_3dlut_fl_format format = 0;
- enum hubp_3dlut_fl_mode mode;
- enum hubp_3dlut_fl_width width = 0;
- enum hubp_3dlut_fl_addressing_mode addr_mode;
- enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_y_g = 0;
- enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cb_b = 0;
- enum hubp_3dlut_fl_crossbar_bit_slice crossbar_bit_slice_cr_r = 0;
- enum MCM_LUT_XABLE shaper_xable = MCM_LUT_DISABLE;
- enum MCM_LUT_XABLE lut3d_xable = MCM_LUT_DISABLE;
- enum MCM_LUT_XABLE lut1d_xable = MCM_LUT_DISABLE;
+ struct dc_3dlut_dma lut3d_dma;
+ bool lut_enable;
+ bool lut_bank_a;
bool rval;
+ bool result = true;
- dcn401_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, &shaper_xable, &lut3d_xable, &lut1d_xable);
+ /* 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);
+ }
+
+ /* 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 */
- if (mcm_luts.lut1d_func) {
- memset(&m_lut_params, 0, sizeof(m_lut_params));
- if (mcm_luts.lut1d_func->type == TF_TYPE_HWPWL)
- m_lut_params.pwl = &mcm_luts.lut1d_func->pwl;
- else if (mcm_luts.lut1d_func->type == TF_TYPE_DISTRIBUTED_POINTS) {
- rval = cm3_helper_translate_curve_to_hw_format(mpc->ctx,
- mcm_luts.lut1d_func,
- &dpp_base->regamma_params, false);
+ lut_enable = cm->flags.bits.blend_enable;
+ 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(plane_state->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 (!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 (mcm_luts.shaper && mcm_luts.lut3d_data.mpc_3dlut_enable) {
+ lut_enable = cm->flags.bits.shaper_enable;
+ if (lut_enable) {
memset(&m_lut_params, 0, sizeof(m_lut_params));
- if (mcm_luts.shaper->type == TF_TYPE_HWPWL)
- m_lut_params.pwl = &mcm_luts.shaper->pwl;
- else if (mcm_luts.shaper->type == TF_TYPE_DISTRIBUTED_POINTS) {
+ 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,
- mcm_luts.shaper,
- &dpp_base->regamma_params, true);
- m_lut_params.pwl = rval ? &dpp_base->regamma_params : NULL;
+ rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
+ &cm->shaper_func,
+ &dpp_base->shaper_params,
+ true);
+ m_lut_params.pwl = rval ? &dpp_base->shaper_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);
+ if (!m_lut_params.pwl) {
+ lut_enable = false;
}
+ } else {
+ lut_enable = false;
}
- /* 3DLUT */
- switch (lut3d_src) {
- case DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM:
- memset(&m_lut_params, 0, sizeof(m_lut_params));
- if (hubp->funcs->hubp_enable_3dlut_fl)
- hubp->funcs->hubp_enable_3dlut_fl(hubp, false);
-
- if (mcm_luts.lut3d_data.lut3d_func && mcm_luts.lut3d_data.lut3d_func->state.bits.initialized) {
- m_lut_params.lut3d = &mcm_luts.lut3d_data.lut3d_func->lut_3d;
- if (mpc->funcs->populate_lut)
- mpc->funcs->populate_lut(mpc, MCM_LUT_3DLUT, m_lut_params, lut_bank_a, mpcc_id);
- if (mpc->funcs->program_lut_mode)
- mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a,
- mpcc_id);
- }
- break;
- case DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM:
- switch (mcm_luts.lut3d_data.gpu_mem_params.size) {
- case DC_CM2_GPU_MEM_SIZE_171717:
- width = hubp_3dlut_fl_width_17;
- break;
- case DC_CM2_GPU_MEM_SIZE_TRANSFORMED:
- width = hubp_3dlut_fl_width_transformed;
- break;
- default:
- //TODO: handle default case
- break;
- }
+ 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))
- break;
+ /* 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;
+ 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);
-
- if (hubp->funcs->hubp_program_3dlut_fl_addr)
- hubp->funcs->hubp_program_3dlut_fl_addr(hubp, mcm_luts.lut3d_data.gpu_mem_params.addr);
+ mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut_enable, lut_bank_a, cm->lut3d_dma.size, mpcc_id);
- if (mpc->funcs->mcm.program_bit_depth)
- mpc->funcs->mcm.program_bit_depth(mpc, mcm_luts.lut3d_data.gpu_mem_params.bit_depth, mpcc_id);
-
- switch (mcm_luts.lut3d_data.gpu_mem_params.layout) {
- case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB:
- mode = hubp_3dlut_fl_mode_native_1;
- addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
- break;
- case DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR:
- mode = hubp_3dlut_fl_mode_native_2;
- addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
- break;
- case DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR:
- mode = hubp_3dlut_fl_mode_transform;
- addr_mode = hubp_3dlut_fl_addressing_mode_simple_linear;
- break;
- default:
- mode = hubp_3dlut_fl_mode_disable;
- addr_mode = hubp_3dlut_fl_addressing_mode_sw_linear;
- break;
- }
- 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, hubp->inst);
- switch (mcm_luts.lut3d_data.gpu_mem_params.format_params.format) {
- case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB:
- format = hubp_3dlut_fl_format_unorm_12msb_bitslice;
- break;
- case DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB:
- format = hubp_3dlut_fl_format_unorm_12lsb_bitslice;
- break;
- case DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10:
- format = hubp_3dlut_fl_format_float_fp1_5_10;
- break;
- }
- if (hubp->funcs->hubp_program_3dlut_fl_format)
- hubp->funcs->hubp_program_3dlut_fl_format(hubp, format);
- if (hubp->funcs->hubp_update_3dlut_fl_bias_scale &&
- mpc->funcs->mcm.program_bias_scale) {
- mpc->funcs->mcm.program_bias_scale(mpc,
- mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias,
- mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale,
- mpcc_id);
- hubp->funcs->hubp_update_3dlut_fl_bias_scale(hubp,
- mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.bias,
- mcm_luts.lut3d_data.gpu_mem_params.format_params.float_params.scale);
- }
-
- //navi 4x has a bug and r and blue are swapped and need to be worked around here in
- //TODO: need to make a method for get_xbar per asic OR do the workaround in program_crossbar for 4x
- switch (mcm_luts.lut3d_data.gpu_mem_params.component_order) {
- case DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA:
- default:
- 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;
- break;
- }
+ /* 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_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);
+ hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp, cm->lut3d_dma.format);
- if (mpc->funcs->update_3dlut_fast_load_select)
- mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, hubp->inst);
+ if (hubp->funcs->hubp_program_3dlut_fl_addr)
+ hubp->funcs->hubp_program_3dlut_fl_addr(hubp, &cm->lut3d_dma.addr);
- if (hubp->funcs->hubp_enable_3dlut_fl)
+ 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);
- }
+ } else {
+ /* GPU memory only supports fast load path */
+ BREAK_TO_DEBUGGER();
+ lut_enable = false;
+ result = false;
}
- break;
+ } else {
+ /* Legacy (Host) Load Mode */
+ memset(&m_lut_params, 0, sizeof(m_lut_params));
- }
-}
+ 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)
-{
- 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->mcm_luts.lut3d_data.lut3d_src == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM) {
- dcn401_populate_mcm_luts(dc, pipe_ctx, plane_state->mcm_luts, 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->blend_tf.type == TF_TYPE_HWPWL)
- lut_params = &plane_state->blend_tf.pwl;
- else if (plane_state->blend_tf.type == TF_TYPE_DISTRIBUTED_POINTS) {
- rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
- &plane_state->blend_tf,
- &dpp_base->regamma_params, false);
- lut_params = rval ? &dpp_base->regamma_params : NULL;
- }
- result = mpc->funcs->program_1dlut(mpc, lut_params, mpcc_id);
- lut_params = NULL;
-
- // Shaper
- if (plane_state->in_shaper_func.type == TF_TYPE_HWPWL)
- lut_params = &plane_state->in_shaper_func.pwl;
- else if (plane_state->in_shaper_func.type == TF_TYPE_DISTRIBUTED_POINTS) {
- // TODO: dpp_base replace
- rval = cm3_helper_translate_curve_to_hw_format(plane_state->ctx,
- &plane_state->in_shaper_func,
- &dpp_base->shaper_params, true);
- lut_params = rval ? &dpp_base->shaper_params : NULL;
- }
- result &= mpc->funcs->program_shaper(mpc, lut_params, mpcc_id);
-
- // 3D
- if (mpc->funcs->program_3dlut) {
- if (plane_state->lut3d_func.state.bits.initialized == 1)
- result &= mpc->funcs->program_3dlut(mpc, &plane_state->lut3d_func.lut_3d, mpcc_id);
- else
- result &= mpc->funcs->program_3dlut(mpc, NULL, mpcc_id);
+ if (hubp->funcs->hubp_enable_3dlut_fl)
+ hubp->funcs->hubp_enable_3dlut_fl(hubp, false);
}
return result;
@@ -673,6 +557,7 @@ bool dcn401_set_output_transfer_func(struct dc *dc,
struct pipe_ctx *pipe_ctx,
const struct dc_stream_state *stream)
{
+ (void)dc;
int mpcc_id = pipe_ctx->plane_res.hubp->inst;
struct mpc *mpc = pipe_ctx->stream_res.opp->ctx->dc->res_pool->mpc;
const struct pwl_params *params = NULL;
@@ -734,6 +619,7 @@ static void enable_stream_timing_calc(
struct drr_params *params,
unsigned int *event_triggers)
{
+ (void)dc;
struct dc_stream_state *stream = pipe_ctx->stream;
int i;
@@ -987,6 +873,8 @@ void dcn401_enable_stream(struct pipe_ctx *pipe_ctx)
}
}
+ link_hwss->setup_stream_attribute(pipe_ctx);
+
if (dc->res_pool->dccg->funcs->set_pixel_rate_div) {
dc->res_pool->dccg->funcs->set_pixel_rate_div(
dc->res_pool->dccg,
@@ -1211,6 +1099,25 @@ void dcn401_set_cursor_position(struct pipe_ctx *pipe_ctx)
x_pos = pos_cpy.x - param.recout.x;
y_pos = pos_cpy.y - param.recout.y;
+ /**
+ * If the cursor position is negative after recout adjustment, we need
+ * to shift the hotspot to compensate and clamp position to 0. This
+ * handles the case where cursor straddles the left/top edge of an
+ * overlay plane - the cursor is partially visible and needs correct
+ * hotspot adjustment to render the visible portion.
+ */
+ if (x_pos < 0) {
+ pos_cpy.x_hotspot -= x_pos;
+ if (hubp->curs_attr.attribute_flags.bits.ENABLE_MAGNIFICATION)
+ adjust_hotspot_between_slices_for_2x_magnify(hubp->curs_attr.width, &pos_cpy);
+ x_pos = 0;
+ }
+
+ if (y_pos < 0) {
+ pos_cpy.y_hotspot -= y_pos;
+ y_pos = 0;
+ }
+
recout_x_pos = x_pos - pos_cpy.x_hotspot;
recout_y_pos = y_pos - pos_cpy.y_hotspot;
@@ -1473,7 +1380,7 @@ void dcn401_optimize_bandwidth(
dc->clk_mgr,
context,
true);
- if (context->bw_ctx.bw.dcn.clk.zstate_support == DCN_ZSTATE_SUPPORT_ALLOW) {
+ if (context->bw_ctx.bw.dcn.clk.zstate_support != DCN_ZSTATE_SUPPORT_DISALLOW) {
for (i = 0; i < dc->res_pool->pipe_count; ++i) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
@@ -1481,7 +1388,7 @@ void dcn401_optimize_bandwidth(
&& pipe_ctx->stream->adjust.v_total_min == pipe_ctx->stream->adjust.v_total_max
&& pipe_ctx->stream->adjust.v_total_max > pipe_ctx->stream->timing.v_total)
pipe_ctx->plane_res.hubp->funcs->program_extended_blank(pipe_ctx->plane_res.hubp,
- pipe_ctx->dlg_regs.min_dst_y_next_start);
+ pipe_ctx->hubp_regs.dlg_regs.min_dst_y_next_start);
}
}
}
@@ -1490,6 +1397,7 @@ void dcn401_dmub_hw_control_lock(struct dc *dc,
struct dc_state *context,
bool lock)
{
+ (void)context;
/* use always for now */
union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
@@ -1916,10 +1824,9 @@ void dcn401_perform_3dlut_wa_unlock(struct pipe_ctx *pipe_ctx)
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->mcm_luts.lut3d_data.lut3d_src
- == DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM
- && mpc_pipe->plane_state->mcm_shaper_3dlut_setting
- == DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT) {
+ 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;
}
}
@@ -1965,10 +1872,10 @@ void dcn401_reset_back_end_for_pipe(
struct pipe_ctx *pipe_ctx,
struct dc_state *context)
{
+ (void)context;
struct dc_link *link = pipe_ctx->stream->link;
const struct link_hwss *link_hwss = get_link_hwss(link, &pipe_ctx->link_res);
- DC_LOGGER_INIT(dc->ctx->logger);
if (pipe_ctx->stream_res.stream_enc == NULL) {
pipe_ctx->stream = NULL;
return;
@@ -2021,7 +1928,7 @@ void dcn401_reset_back_end_for_pipe(
* the case where the same symclk is shared across multiple otg
* instances
*/
- if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal))
+ if (dc_is_tmds_signal(pipe_ctx->stream->signal))
link->phy_state.symclk_ref_cnts.otg = 0;
if (link->phy_state.symclk_state == SYMCLK_ON_TX_OFF) {
link_hwss->disable_link_output(link,
@@ -2047,6 +1954,22 @@ void dcn401_reset_back_end_for_pipe(
DC_LOG_DEBUG("Reset back end for pipe %d, tg:%d\n",
pipe_ctx->pipe_idx, pipe_ctx->stream_res.tg->inst);
}
+static void dc_hwss_disable_otg_pwa(struct dc *dc)
+{
+ if (dc->debug.enable_otg_frame_sync_pwa) {
+ int i;
+
+ /*reset all the otg*/
+ for (i = dc->res_pool->timing_generator_count - 1; i >= 0 ; i--) {
+ struct timing_generator *tg = dc->res_pool->timing_generators[i];
+
+ if (tg->funcs->disable_otg_pwa) {
+ tg->funcs->disable_otg_pwa(tg);
+ DC_LOG_DC("otg frame sync pwa disabled on otg%d\n", tg->inst);
+ }
+ }
+ }
+}
void dcn401_reset_hw_ctx_wrap(
struct dc *dc,
@@ -2055,6 +1978,7 @@ void dcn401_reset_hw_ctx_wrap(
int i;
struct dce_hwseq *hws = dc->hwseq;
+ dc_hwss_disable_otg_pwa(dc);
/* Reset Back End*/
for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
struct pipe_ctx *pipe_ctx_old =
@@ -2245,6 +2169,10 @@ void dcn401_program_pipe(
pipe_ctx->stream_res.test_pattern_params.height,
pipe_ctx->stream_res.test_pattern_params.offset);
}
+ if (pipe_ctx->plane_state
+ && pipe_ctx->plane_state->update_flags.bits.cm_hist_change
+ && hws->funcs.program_cm_hist)
+ hws->funcs.program_cm_hist(dc, pipe_ctx, pipe_ctx->plane_state);
}
/*
@@ -2396,6 +2324,13 @@ void dcn401_program_pipe_sequence(
pipe_ctx->stream_res.test_pattern_params.offset);
}
+ if (pipe_ctx->plane_state
+ && pipe_ctx->plane_state->update_flags.bits.cm_hist_change
+ && hws->funcs.program_cm_hist) {
+
+ hwss_add_dpp_program_cm_hist(seq_state, pipe_ctx->plane_res.dpp,
+ pipe_ctx->plane_state->cm_hist_control, pipe_ctx->plane_state->color_space);
+ }
}
void dcn401_program_front_end_for_ctx(
@@ -2408,8 +2343,6 @@ void dcn401_program_front_end_for_ctx(
struct dce_hwseq *hws = dc->hwseq;
struct pipe_ctx *pipe = NULL;
- DC_LOGGER_INIT(dc->ctx->logger);
-
if (resource_is_pipe_topology_changed(dc->current_state, context))
resource_log_pipe_topology_update(dc, context);
@@ -2573,8 +2506,6 @@ void dcn401_post_unlock_program_front_end(
struct dce_hwseq *hwseq = dc->hwseq;
int i;
- DC_LOGGER_INIT(dc->ctx->logger);
-
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))
@@ -2954,8 +2885,6 @@ void dcn401_plane_atomic_power_down(struct dc *dc,
struct dce_hwseq *hws = dc->hwseq;
uint32_t org_ip_request_cntl = 0;
- DC_LOGGER_INIT(dc->ctx->logger);
-
if (REG(DC_IP_REQUEST_CNTL)) {
REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
if (org_ip_request_cntl == 0)
@@ -3047,8 +2976,6 @@ void dcn401_plane_atomic_power_down_sequence(struct dc *dc,
struct dce_hwseq *hws = dc->hwseq;
uint32_t org_ip_request_cntl = 0;
- DC_LOGGER_INIT(dc->ctx->logger);
-
/* Check and set DC_IP_REQUEST_CNTL if needed */
if (REG(DC_IP_REQUEST_CNTL)) {
REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
@@ -3321,6 +3248,7 @@ void dcn401_update_writeback_sequence(
struct dc_state *context,
struct block_sequence_state *seq_state)
{
+ (void)context;
struct dwbc *dwb;
struct mcif_wb *mcif_wb;
@@ -3526,6 +3454,7 @@ void dcn401_enable_plane_sequence(struct dc *dc, struct pipe_ctx *pipe_ctx,
struct dc_state *context,
struct block_sequence_state *seq_state)
{
+ (void)context;
struct dce_hwseq *hws = dc->hwseq;
uint32_t org_ip_request_cntl = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
new file mode 100644
index 000000000000..46f2f9833d9e
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.c
@@ -0,0 +1,1104 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dm_services.h"
+#include "dm_helpers.h"
+#include "core_types.h"
+#include "resource.h"
+#include "dccg.h"
+#include "dce/dce_hwseq.h"
+#include "dcn30/dcn30_cm_common.h"
+#include "reg_helper.h"
+#include "abm.h"
+#include "hubp.h"
+#include "dchubbub.h"
+#include "timing_generator.h"
+#include "opp.h"
+#include "ipp.h"
+#include "mpc.h"
+#include "mcif_wb.h"
+#include "dc_dmub_srv.h"
+#include "link_hwss.h"
+#include "dpcd_defs.h"
+#include "dcn401/dcn401_hwseq.h"
+#include "dcn42_hwseq.h"
+#include "clk_mgr.h"
+#include "dsc.h"
+#include "dcn20/dcn20_optc.h"
+#include "dce/dmub_hw_lock_mgr.h"
+#include "dcn42/dcn42_resource.h"
+#include "link_service.h"
+#include "../dcn10/dcn10_hwseq.h"
+#include "../dcn20/dcn20_hwseq.h"
+#include "dc_state_priv.h"
+#include "dc_stream_priv.h"
+#include "dcn35/dcn35_hwseq.h"
+#include "dcn42/dcn42_hwseq.h"
+#include "dce/dmub_hw_lock_mgr.h"
+#include "dio/dcn10/dcn10_dio.h"
+
+#define DC_LOGGER \
+ ctx->logger
+
+#define CTX \
+ hws->ctx
+
+#define REG(reg)\
+ hws->regs->reg
+
+#undef FN
+#define FN(reg_name, field_name) \
+ hws->shifts->field_name, hws->masks->field_name
+
+
+static void print_pg_status(struct dc *dc, const char *debug_func, const char *debug_log)
+{
+ if (dc->debug.enable_pg_cntl_debug_logs && dc->res_pool->pg_cntl) {
+ if (dc->res_pool->pg_cntl->funcs->print_pg_status)
+ dc->res_pool->pg_cntl->funcs->print_pg_status(dc->res_pool->pg_cntl, debug_func, debug_log);
+ }
+}
+void dcn42_init_hw(struct dc *dc)
+{
+ struct abm **abms = dc->res_pool->multiple_abms;
+ struct dce_hwseq *hws = dc->hwseq;
+ struct dc_bios *dcb = dc->ctx->dc_bios;
+ struct resource_pool *res_pool = dc->res_pool;
+ int i;
+ unsigned int edp_num;
+ uint32_t backlight = MAX_BACKLIGHT_LEVEL;
+ uint32_t user_level = MAX_BACKLIGHT_LEVEL;
+ bool dchub_ref_freq_changed;
+ int current_dchub_ref_freq = 0;
+
+ if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->init_clocks) {
+ dc->clk_mgr->funcs->init_clocks(dc->clk_mgr);
+
+ // mark dcmode limits present if any clock has distinct AC and DC values from SMU
+ dc->caps.dcmode_power_limits_present = dc->clk_mgr->funcs->is_dc_mode_present &&
+ dc->clk_mgr->funcs->is_dc_mode_present(dc->clk_mgr);
+ }
+
+ // Initialize the dccg
+ if (res_pool->dccg->funcs->dccg_init)
+ res_pool->dccg->funcs->dccg_init(res_pool->dccg);
+
+ // Disable DMUB Initialization until IPS state programming is finalized
+ //if (!dcb->funcs->is_accelerated_mode(dcb)) {
+ // hws->funcs.bios_golden_init(dc);
+ //}
+
+ // Set default OPTC memory power states
+ if (dc->debug.enable_mem_low_power.bits.optc) {
+ // Shutdown when unassigned and light sleep in VBLANK
+ REG_SET_2(ODM_MEM_PWR_CTRL3, 0, ODM_MEM_UNASSIGNED_PWR_MODE, 3, ODM_MEM_VBLANK_PWR_MODE, 1);
+ }
+
+ if (dc->debug.enable_mem_low_power.bits.vga) {
+ // Power down VGA memory
+ REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1);
+ }
+
+ if (dc->ctx->dc_bios->fw_info_valid) {
+ res_pool->ref_clocks.xtalin_clock_inKhz =
+ dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency;
+
+ if (res_pool->hubbub) {
+ (res_pool->dccg->funcs->get_dccg_ref_freq)(res_pool->dccg,
+ dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency,
+ &res_pool->ref_clocks.dccg_ref_clock_inKhz);
+
+ current_dchub_ref_freq = res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;
+
+ (res_pool->hubbub->funcs->get_dchub_ref_freq)(res_pool->hubbub,
+ res_pool->ref_clocks.dccg_ref_clock_inKhz,
+ &res_pool->ref_clocks.dchub_ref_clock_inKhz);
+ } else {
+ // Not all ASICs have DCCG sw component
+ res_pool->ref_clocks.dccg_ref_clock_inKhz =
+ res_pool->ref_clocks.xtalin_clock_inKhz;
+ res_pool->ref_clocks.dchub_ref_clock_inKhz =
+ res_pool->ref_clocks.xtalin_clock_inKhz;
+ }
+ } else
+ ASSERT_CRITICAL(false);
+
+ for (i = 0; i < dc->link_count; i++) {
+ /* Power up AND update implementation according to the
+ * required signal (which may be different from the
+ * default signal on connector).
+ */
+ struct dc_link *link = dc->links[i];
+
+ if (link->ep_type != DISPLAY_ENDPOINT_PHY)
+ continue;
+
+ link->link_enc->funcs->hw_init(link->link_enc);
+
+ /* Check for enabled DIG to identify enabled display */
+ if (link->link_enc->funcs->is_dig_enabled &&
+ link->link_enc->funcs->is_dig_enabled(link->link_enc)) {
+ link->link_status.link_active = true;
+ link->phy_state.symclk_state = SYMCLK_ON_TX_ON;
+ if (link->link_enc->funcs->fec_is_active &&
+ link->link_enc->funcs->fec_is_active(link->link_enc))
+ link->fec_state = dc_link_fec_enabled;
+ }
+ }
+
+ /* enable_power_gating_plane before dsc_pg_control because
+ * FORCEON = 1 with hw default value on bootup, resume from s3
+ */
+ if (hws->funcs.enable_power_gating_plane)
+ hws->funcs.enable_power_gating_plane(dc->hwseq, true);
+
+ /* we want to turn off all dp displays before doing detection */
+ dc->link_srv->blank_all_dp_displays(dc);
+
+ /* If taking control over from VBIOS, we may want to optimize our first
+ * mode set, so we need to skip powering down pipes until we know which
+ * pipes we want to use.
+ * Otherwise, if taking control is not possible, we need to power
+ * everything down.
+ */
+ if (dcb->funcs->is_accelerated_mode(dcb) || !dc->config.seamless_boot_edp_requested) {
+ /* Disable boot optimizations means power down everything including PHY, DIG,
+ * and OTG (i.e. the boot is not optimized because we do a full power down).
+ */
+ if (dc->hwss.enable_accelerated_mode && dc->debug.disable_boot_optimizations)
+ dc->hwss.enable_accelerated_mode(dc, dc->current_state);
+ else
+ hws->funcs.init_pipes(dc, dc->current_state);
+
+ if (dc->res_pool->hubbub->funcs->allow_self_refresh_control)
+ dc->res_pool->hubbub->funcs->allow_self_refresh_control(dc->res_pool->hubbub,
+ !dc->res_pool->hubbub->ctx->dc->debug.disable_stutter);
+
+ }
+
+ /* In headless boot cases, DIG may be turned
+ * on which causes HW/SW discrepancies.
+ * To avoid this, power down hardware on boot
+ * if DIG is turned on and seamless boot not enabled
+ */
+ if (!dc->config.seamless_boot_edp_requested) {
+ struct dc_link *edp_links[MAX_NUM_EDP];
+ struct dc_link *edp_link;
+
+ dc_get_edp_links(dc, edp_links, &edp_num);
+ if (edp_num) {
+ for (i = 0; i < edp_num; i++) {
+ edp_link = edp_links[i];
+ if (edp_link->link_enc->funcs->is_dig_enabled &&
+ edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
+ dc->hwss.edp_backlight_control &&
+ hws->funcs.power_down &&
+ dc->hwss.edp_power_control) {
+ dc->hwss.edp_backlight_control(edp_link, false);
+ hws->funcs.power_down(dc);
+ dc->hwss.edp_power_control(edp_link, false);
+ }
+ }
+ } else {
+ for (i = 0; i < dc->link_count; i++) {
+ struct dc_link *link = dc->links[i];
+
+ if (link && link->link_enc &&
+ link->link_enc->funcs->is_dig_enabled &&
+ link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
+ hws->funcs.power_down) {
+ hws->funcs.power_down(dc);
+ break;
+ }
+
+ }
+ }
+ }
+
+ for (i = 0; i < res_pool->audio_count; i++) {
+ struct audio *audio = res_pool->audios[i];
+
+ audio->funcs->hw_init(audio);
+ }
+
+ for (i = 0; i < dc->link_count; i++) {
+ struct dc_link *link = dc->links[i];
+
+ if (link->panel_cntl) {
+ backlight = link->panel_cntl->funcs->hw_init(link->panel_cntl);
+ user_level = link->panel_cntl->stored_backlight_registers.USER_LEVEL;
+ }
+ }
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (abms[i] != NULL && abms[i]->funcs != NULL)
+ abms[i]->funcs->abm_init(abms[i], backlight, user_level);
+ }
+
+ /* power AFMT HDMI memory TODO: may move to dis/en output save power*/
+ if (dc->res_pool->dio && dc->res_pool->dio->funcs->mem_pwr_ctrl)
+ dc->res_pool->dio->funcs->mem_pwr_ctrl(dc->res_pool->dio, false);
+
+ if (!dc->debug.disable_clock_gate) {
+ /* enable all DCN clock gating */
+ REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0);
+
+ REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);
+ }
+
+ dcn401_setup_hpo_hw_control(hws, true);
+
+ if (!dcb->funcs->is_accelerated_mode(dcb) && dc->res_pool->hubbub->funcs->init_watermarks)
+ dc->res_pool->hubbub->funcs->init_watermarks(dc->res_pool->hubbub);
+
+ if (dc->clk_mgr && dc->clk_mgr->funcs && dc->clk_mgr->funcs->notify_wm_ranges)
+ dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
+
+ if (dc->res_pool->hubbub->funcs->force_pstate_change_control)
+ dc->res_pool->hubbub->funcs->force_pstate_change_control(
+ dc->res_pool->hubbub, false, false);
+
+ if (dc->res_pool->hubbub->funcs->init_crb)
+ dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
+
+ if (dc->res_pool->hubbub->funcs->set_request_limit &&
+ dc->clk_mgr && dc->clk_mgr->bw_params &&
+ dc->config.sdpif_request_limit_words_per_umc > 0)
+ dc->res_pool->hubbub->funcs->set_request_limit(dc->res_pool->hubbub,
+ dc->clk_mgr->bw_params->num_channels,
+ dc->config.sdpif_request_limit_words_per_umc);
+
+ // Get DMCUB capabilities
+ if (dc->ctx->dmub_srv) {
+ dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv);
+ dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
+ dc->caps.dmub_caps.mclk_sw = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver > 0;
+ dc->caps.dmub_caps.fams_ver = dc->ctx->dmub_srv->dmub->feature_caps.fw_assisted_mclk_switch_ver;
+
+ /* sw and fw FAMS versions must match for support */
+ dc->debug.fams2_config.bits.enable &=
+ dc->caps.dmub_caps.fams_ver == dc->debug.fams_version.ver;
+ dchub_ref_freq_changed =
+ res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000 != current_dchub_ref_freq;
+
+ if ((!dc->debug.fams2_config.bits.enable || dchub_ref_freq_changed) &&
+ dc->res_pool->funcs->update_bw_bounding_box &&
+ dc->clk_mgr && dc->clk_mgr->bw_params) {
+ /* update bounding box if FAMS2 disabled, or if dchub clk has changed */
+ dc->res_pool->funcs->update_bw_bounding_box(dc, dc->clk_mgr->bw_params);
+ }
+ }
+ if (dc->res_pool->pg_cntl) {
+ if (dc->res_pool->pg_cntl->funcs->init_pg_status)
+ dc->res_pool->pg_cntl->funcs->init_pg_status(dc->res_pool->pg_cntl);
+ }
+ print_pg_status(dc, __func__, ": after init_pg_status");
+}
+
+void dcn42_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx)
+{
+ struct hubp *hubp = pipe_ctx->plane_res.hubp;
+ struct mpcc_blnd_cfg blnd_cfg = {0};
+ bool per_pixel_alpha = pipe_ctx->plane_state->per_pixel_alpha;
+ int mpcc_id;
+ struct mpcc *new_mpcc;
+ struct mpc *mpc = dc->res_pool->mpc;
+ struct mpc_tree *mpc_tree_params = &(pipe_ctx->stream_res.opp->mpc_tree_params);
+
+
+ blnd_cfg.overlap_only = false;
+ blnd_cfg.global_gain = 0xfff;
+
+ if (per_pixel_alpha) {
+ blnd_cfg.pre_multiplied_alpha = pipe_ctx->plane_state->pre_multiplied_alpha;
+ if (pipe_ctx->plane_state->global_alpha) {
+ blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA_COMBINED_GLOBAL_GAIN;
+ blnd_cfg.global_gain = pipe_ctx->plane_state->global_alpha_value;
+ } else {
+ blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA;
+ }
+ } else {
+ blnd_cfg.pre_multiplied_alpha = false;
+ blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA;
+ }
+
+ if (pipe_ctx->plane_state->global_alpha)
+ blnd_cfg.global_alpha = pipe_ctx->plane_state->global_alpha_value;
+ else
+ blnd_cfg.global_alpha = 0xfff;
+
+ blnd_cfg.background_color_bpc = 4;
+ blnd_cfg.bottom_gain_mode = 0;
+ blnd_cfg.top_gain = 0x1f000;
+ blnd_cfg.bottom_inside_gain = 0x1f000;
+ blnd_cfg.bottom_outside_gain = 0x1f000;
+
+ if (pipe_ctx->plane_state->format
+ == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA)
+ blnd_cfg.pre_multiplied_alpha = false;
+
+ /*
+ * TODO: remove hack
+ * Note: currently there is a bug in init_hw such that
+ * on resume from hibernate, BIOS sets up MPCC0, and
+ * we do mpcc_remove but the mpcc cannot go to idle
+ * after remove. This cause us to pick mpcc1 here,
+ * which causes a pstate hang for yet unknown reason.
+ */
+ mpcc_id = hubp->inst;
+
+ /* If there is no full update, don't need to touch MPC tree*/
+ if (!pipe_ctx->plane_state->update_flags.bits.full_update &&
+ !pipe_ctx->update_flags.bits.mpcc) {
+ mpc->funcs->update_blending(mpc, &blnd_cfg, mpcc_id);
+ dc->hwss.update_visual_confirm_color(dc, pipe_ctx, mpcc_id);
+ return;
+ }
+
+ /* check if this MPCC is already being used */
+ new_mpcc = mpc->funcs->get_mpcc_for_dpp(mpc_tree_params, mpcc_id);
+ /* remove MPCC if being used */
+ if (new_mpcc != NULL)
+ mpc->funcs->remove_mpcc(mpc, mpc_tree_params, new_mpcc);
+ else
+ if (dc->debug.sanity_checks)
+ mpc->funcs->assert_mpcc_idle_before_connect(
+ dc->res_pool->mpc, mpcc_id);
+
+ /* Call MPC to insert new plane */
+ new_mpcc = mpc->funcs->insert_plane(dc->res_pool->mpc,
+ mpc_tree_params,
+ &blnd_cfg,
+ NULL,
+ NULL,
+ hubp->inst,
+ mpcc_id);
+ dc->hwss.update_visual_confirm_color(dc, pipe_ctx, mpcc_id);
+
+ ASSERT(new_mpcc != NULL);
+ hubp->opp_id = pipe_ctx->stream_res.opp->inst;
+ hubp->mpcc_id = mpcc_id;
+}
+
+void dcn42_program_cm_hist(
+ struct dc *dc,
+ struct pipe_ctx *pipe_ctx,
+ const struct dc_plane_state *plane_state)
+{
+ (void)dc;
+ struct dpp *dpp = pipe_ctx->plane_res.dpp;
+
+ if (dpp && dpp->funcs->dpp_cm_hist_control)
+ dpp->funcs->dpp_cm_hist_control(dpp,
+ plane_state->cm_hist_control, plane_state->color_space);
+}
+
+static bool dc_is_rmcm_3dlut_supported(struct hubp *hubp, struct mpc *mpc)
+{
+ if (mpc->funcs->rmcm.power_on_shaper_3dlut &&
+ mpc->funcs->rmcm.fl_3dlut_configure &&
+ hubp->funcs->hubp_program_3dlut_fl_config)
+ return true;
+
+ return false;
+}
+
+bool dcn42_program_rmcm_luts(
+ struct hubp *hubp,
+ struct pipe_ctx *pipe_ctx,
+ const struct dc_plane_cm *cm,
+ struct mpc *mpc,
+ int mpcc_id)
+{
+ struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
+ union mcm_lut_params m_lut_params = {0};
+
+ struct dc *dc = hubp->ctx->dc;
+ struct mpc_fl_3dlut_config mpc_fl_config;
+
+ struct dc_stream_state *stream = pipe_ctx->stream;
+ bool bypass_rmcm_shaper = false;
+ // true->false when it can be allocated at DI time
+ struct dc_rmcm_3dlut *rmcm_3dlut = dc_stream_get_3dlut_for_stream(dc, stream, false);
+
+ bool lut_bank_a = true; // TODO get from HW
+
+ //check to see current pipe is part of a stream with allocated rmcm 3dlut
+ if (!rmcm_3dlut)
+ return false;
+
+ /* Shaper */
+ if (cm->flags.bits.shaper_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);
+ cm_helper_translate_curve_to_hw_format(
+ dc->ctx,
+ &cm->shaper_func,
+ &dpp_base->shaper_params, true);
+ m_lut_params.pwl = &dpp_base->shaper_params;
+ }
+ if (m_lut_params.pwl) {
+ if (mpc->funcs->rmcm.populate_lut)
+ mpc->funcs->rmcm.populate_lut(mpc, m_lut_params, lut_bank_a, mpcc_id);
+ if (mpc->funcs->rmcm.program_lut_mode)
+ mpc->funcs->rmcm.program_lut_mode(mpc, !bypass_rmcm_shaper, lut_bank_a, mpcc_id);
+ } else {
+ //RMCM 3dlut won't work without its shaper
+ return false;
+ }
+ }
+
+ /* 3DLUT */
+ if (!cm->flags.bits.lut3d_dma_enable) {
+ memset(&m_lut_params, 0, sizeof(m_lut_params));
+ // Don't know what to do in this case.
+ } else {
+ if (!dc_is_rmcm_3dlut_supported(hubp, mpc))
+ return false;
+
+ //seems to be only for the MCM
+ mpc_fl_config.enabled = cm->flags.bits.lut3d_enable;
+ mpc_fl_config.size = cm->lut3d_dma.size;
+ mpc_fl_config.select_lut_bank_a = lut_bank_a;
+ mpc_fl_config.bit_depth = 0;
+ mpc_fl_config.hubp_index = hubp->inst;
+ mpc_fl_config.bias = cm->lut3d_dma.bias;
+ mpc_fl_config.scale = cm->lut3d_dma.scale;
+
+ //1. power down the block
+ mpc->funcs->rmcm.power_on_shaper_3dlut(mpc, mpcc_id, false);
+
+ //2. program RMCM - 3dlut reg programming
+ mpc->funcs->rmcm.fl_3dlut_configure(mpc, &mpc_fl_config, mpcc_id);
+
+ /* HUBP */
+ 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);
+ }
+
+ return true;
+}
+
+bool dcn42_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;
+ 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;
+ bool result;
+
+ /* MCM */
+ result = dcn401_set_mcm_luts(pipe_ctx, plane_state);
+
+ /* RMCM */
+ 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;
+}
+void dcn42_hardware_release(struct dc *dc)
+{
+ dcn35_hardware_release(dc);
+
+}
+static int count_active_streams(const struct dc *dc)
+{
+ int i, count = 0;
+
+ for (i = 0; i < dc->current_state->stream_count; ++i) {
+ struct dc_stream_state *stream = dc->current_state->streams[i];
+
+ if (stream && (!stream->dpms_off || dc->config.disable_ips_in_dpms_off))
+ count += 1;
+ }
+
+ return count;
+}
+
+void dcn42_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,
+ struct pg_block_update *update_state)
+{
+ bool hpo_frl_stream_enc_acquired = false;
+ bool hpo_dp_stream_enc_acquired = false;
+ int i = 0, j = 0;
+
+ memset(update_state, 0, sizeof(struct pg_block_update));
+
+ update_state->pg_res_update[PG_DIO] = true;
+
+ for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) {
+ if (context->res_ctx.is_hpo_dp_stream_enc_acquired[i] &&
+ dc->res_pool->hpo_dp_stream_enc[i]) {
+ hpo_dp_stream_enc_acquired = true;
+ break;
+ }
+ }
+
+ if (!hpo_frl_stream_enc_acquired && !hpo_dp_stream_enc_acquired)
+ update_state->pg_res_update[PG_HPO] = true;
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
+
+ for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++)
+ update_state->pg_pipe_res_update[j][i] = true;
+
+ if (!pipe_ctx)
+ continue;
+
+ if (pipe_ctx->plane_res.hubp)
+ update_state->pg_pipe_res_update[PG_HUBP][pipe_ctx->plane_res.hubp->inst] = false;
+
+ if (pipe_ctx->plane_res.dpp && pipe_ctx->plane_res.hubp)
+ update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->plane_res.hubp->inst] = false;
+
+ if (pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp)
+ update_state->pg_pipe_res_update[PG_MPCC][pipe_ctx->plane_res.mpcc_inst] = false;
+
+ if (pipe_ctx->stream_res.dsc) {
+ update_state->pg_pipe_res_update[PG_DSC][pipe_ctx->stream_res.dsc->inst] = false;
+ if (dc->caps.sequential_ono) {
+ update_state->pg_pipe_res_update[PG_HUBP][pipe_ctx->stream_res.dsc->inst] = false;
+ update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->stream_res.dsc->inst] = false;
+ }
+ }
+ if (pipe_ctx->stream_res.opp)
+ update_state->pg_pipe_res_update[PG_OPP][pipe_ctx->stream_res.opp->inst] = false;
+
+ if (pipe_ctx->stream_res.hpo_dp_stream_enc)
+ update_state->pg_pipe_res_update[PG_DPSTREAM][pipe_ctx->stream_res.hpo_dp_stream_enc->inst] = false;
+
+ if (pipe_ctx->link_res.dio_link_enc) {
+ update_state->pg_res_update[PG_DIO] = false;
+ }
+ if (pipe_ctx->link_res.hpo_dp_link_enc) {
+ update_state->pg_res_update[PG_HPO] = false;
+ }
+ }
+
+
+ for (i = 0; i < dc->link_count; i++) {
+ update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = true;
+ if (dc->links[i]->type != dc_connection_none)
+ update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = false;
+ }
+
+ /*domain24 controls all the otg, mpc, opp, as long as one otg is still up, avoid enabling OTG PG*/
+ for (i = 0; i < dc->res_pool->timing_generator_count; i++) {
+ struct timing_generator *tg = dc->res_pool->timing_generators[i];
+ if (tg && tg->funcs->is_tg_enabled(tg)) {
+ update_state->pg_pipe_res_update[PG_OPTC][i] = false;
+ } else {
+ // Update pg_pipe_res_enable state
+ if (dc->res_pool->pg_cntl->funcs->optc_pg_control)
+ dc->res_pool->pg_cntl->funcs->optc_pg_control(dc->res_pool->pg_cntl, i, false);
+ }
+ }
+
+}
+
+void dcn42_prepare_bandwidth(
+ struct dc *dc,
+ struct dc_state *context)
+{
+
+ struct pg_block_update pg_update_state;
+
+ if (dc->hwss.calc_blocks_to_ungate) {
+ dc->hwss.calc_blocks_to_ungate(dc, context, &pg_update_state);
+
+ if (dc->hwss.root_clock_control)
+ dc->hwss.root_clock_control(dc, &pg_update_state, true);
+ /*power up required HW block*/
+ if (dc->hwss.hw_block_power_up)
+ dc->hwss.hw_block_power_up(dc, &pg_update_state);
+ }
+
+ dcn401_prepare_bandwidth(dc, context);
+}
+
+void dcn42_optimize_bandwidth(struct dc *dc, struct dc_state *context)
+{
+ struct pg_block_update pg_update_state;
+
+ print_pg_status(dc, __func__, ": before rcg and power up");
+
+ dcn401_optimize_bandwidth(dc, context);
+
+ if (dc->hwss.calc_blocks_to_gate) {
+ dc->hwss.calc_blocks_to_gate(dc, context, &pg_update_state);
+ /*try to power down unused block*/
+ if (dc->hwss.hw_block_power_down)
+ dc->hwss.hw_block_power_down(dc, &pg_update_state);
+
+ if (dc->hwss.root_clock_control)
+ dc->hwss.root_clock_control(dc, &pg_update_state, false);
+ }
+
+ print_pg_status(dc, __func__, ": after rcg and power up");
+
+}
+
+void dcn42_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context,
+ struct pg_block_update *update_state)
+{
+ bool hpo_dp_stream_enc_acquired = false;
+ int i = 0, j = 0;
+
+ memset(update_state, 0, sizeof(struct pg_block_update));
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *cur_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+ struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (cur_pipe == NULL || new_pipe == NULL)
+ continue;
+
+ if ((!cur_pipe->plane_state && new_pipe->plane_state) ||
+ (!cur_pipe->stream && new_pipe->stream) ||
+ (cur_pipe->stream != new_pipe->stream && new_pipe->stream)) {
+ // New pipe addition
+ for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++) {
+ if (j == PG_HUBP && new_pipe->plane_res.hubp)
+ update_state->pg_pipe_res_update[j][new_pipe->plane_res.hubp->inst] = true;
+
+ if (j == PG_DPP && new_pipe->plane_res.dpp)
+ update_state->pg_pipe_res_update[j][new_pipe->plane_res.dpp->inst] = true;
+
+ if (j == PG_MPCC && new_pipe->plane_res.dpp)
+ update_state->pg_pipe_res_update[j][new_pipe->plane_res.mpcc_inst] = true;
+
+ if (j == PG_DSC && new_pipe->stream_res.dsc)
+ update_state->pg_pipe_res_update[j][new_pipe->stream_res.dsc->inst] = true;
+
+ if (j == PG_OPP && new_pipe->stream_res.opp)
+ update_state->pg_pipe_res_update[j][new_pipe->stream_res.opp->inst] = true;
+
+ if (j == PG_OPTC && new_pipe->stream_res.tg)
+ update_state->pg_pipe_res_update[j][new_pipe->stream_res.tg->inst] = true;
+
+ if (j == PG_DPSTREAM && new_pipe->stream_res.hpo_dp_stream_enc)
+ update_state->pg_pipe_res_update[j][new_pipe->stream_res.hpo_dp_stream_enc->inst] = true;
+ }
+ } else if (cur_pipe->plane_state == new_pipe->plane_state ||
+ cur_pipe == new_pipe) {
+ //unchanged pipes
+ for (j = 0; j < PG_HW_PIPE_RESOURCES_NUM_ELEMENT; j++) {
+ if (j == PG_HUBP &&
+ cur_pipe->plane_res.hubp != new_pipe->plane_res.hubp &&
+ new_pipe->plane_res.hubp)
+ update_state->pg_pipe_res_update[j][new_pipe->plane_res.hubp->inst] = true;
+
+ if (j == PG_DPP &&
+ cur_pipe->plane_res.dpp != new_pipe->plane_res.dpp &&
+ new_pipe->plane_res.dpp)
+ update_state->pg_pipe_res_update[j][new_pipe->plane_res.dpp->inst] = true;
+
+ if (j == PG_OPP &&
+ cur_pipe->stream_res.opp != new_pipe->stream_res.opp &&
+ new_pipe->stream_res.opp)
+ update_state->pg_pipe_res_update[j][new_pipe->stream_res.opp->inst] = true;
+
+ if (j == PG_DSC &&
+ cur_pipe->stream_res.dsc != new_pipe->stream_res.dsc &&
+ new_pipe->stream_res.dsc)
+ update_state->pg_pipe_res_update[j][new_pipe->stream_res.dsc->inst] = true;
+
+ if (j == PG_OPTC &&
+ cur_pipe->stream_res.tg != new_pipe->stream_res.tg &&
+ new_pipe->stream_res.tg)
+ update_state->pg_pipe_res_update[j][new_pipe->stream_res.tg->inst] = true;
+
+ if (j == PG_DPSTREAM &&
+ cur_pipe->stream_res.hpo_dp_stream_enc != new_pipe->stream_res.hpo_dp_stream_enc &&
+ new_pipe->stream_res.hpo_dp_stream_enc)
+ update_state->pg_pipe_res_update[j][new_pipe->stream_res.hpo_dp_stream_enc->inst] = true;
+ }
+ }
+ }
+
+ for (i = 0; i < dc->link_count; i++)
+ if (dc->links[i]->type != dc_connection_none)
+ update_state->pg_pipe_res_update[PG_PHYSYMCLK][dc->links[i]->link_enc_hw_inst] = true;
+
+ for (i = 0; i < dc->res_pool->stream_enc_count; i++) {
+ if (dc->current_state->res_ctx.is_stream_enc_acquired[i]) {
+ update_state->pg_res_update[PG_DIO] = true;
+ break;
+ }
+ }
+ for (i = 0; i < dc->res_pool->hpo_dp_stream_enc_count; i++) {
+ if (context->res_ctx.is_hpo_dp_stream_enc_acquired[i] &&
+ dc->res_pool->hpo_dp_stream_enc[i]) {
+ hpo_dp_stream_enc_acquired = true;
+ break;
+ }
+ }
+
+ if (hpo_dp_stream_enc_acquired)
+ update_state->pg_res_update[PG_HPO] = true;
+
+ if (count_active_streams(dc) > 0) {
+ update_state->pg_res_update[PG_DCCG] = true;
+ update_state->pg_res_update[PG_DCIO] = true;
+ update_state->pg_res_update[PG_DCHUBBUB] = true;
+ update_state->pg_res_update[PG_DCHVM] = true;
+ update_state->pg_res_update[PG_DCOH] = true;
+ }
+}
+/**
+ * dcn42_hw_block_power_down() - power down sequence
+ *
+ * The following sequence describes the ON-OFF (ONO) for power down:
+ *
+ * ONO Region 4, DCPG 25: hpo
+ * ONO Region 11, DCPG 3: dchubp3, dpp3
+ * ONO Region 9, DCPG 2: dchubp2, dpp2
+ * ONO Region 7, DCPG 1: dchubp1, dpp1
+ * ONO Region 5, DCPG 0: dchubp0, dpp0
+ * ONO Region 2, DCPG 23: dchubbub, dchububmem, dchvm
+ * ONO Region 12, DCPG 19: dsc3
+ * ONO Region 10, DCPG 18: dsc2
+ * ONO Region 8, DCPG 17: dsc1
+ * ONO Region 6, DCPG 16: dsc0
+ * ONO Region 3, DCPG 24: mpc, opp, optc, dwb
+ * ONO Region 1, DCPG 26: dio
+ * ONO Region 0, DCPG 22: dccg dcio dcoh - SKIPPED
+ *
+ * No seuential ONO power up/down order for DCN42
+ * Driver PG should only be limited to DCHUBP/DPP, DSC, HPO and DIO, so further optimization can be done
+ *
+ * @dc: Current DC state
+ * @update_state: update PG sequence states for HW block
+ */
+ void dcn42_hw_block_power_down(struct dc *dc,
+ struct pg_block_update *update_state)
+{
+ int i = 0;
+ struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl;
+ bool block_disabled = true;
+
+ if (!pg_cntl)
+ return;
+ if (dc->debug.ignore_pg)
+ return;
+
+ if (update_state->pg_res_update[PG_HPO]) {
+ if (pg_cntl->funcs->hpo_pg_control)
+ pg_cntl->funcs->hpo_pg_control(pg_cntl, false);
+ }
+
+ for (i = dc->res_pool->pipe_count - 1; i >= 0; i--) {
+ if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
+ update_state->pg_pipe_res_update[PG_DPP][i]) {
+ if (pg_cntl->funcs->hubp_dpp_pg_control)
+ pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, false);
+ }
+ }
+
+ if (update_state->pg_res_update[PG_DCHUBBUB]) {
+ if (pg_cntl->funcs->mem_pg_control)
+ pg_cntl->funcs->mem_pg_control(pg_cntl, false);
+ }
+
+ for (i = dc->res_pool->res_cap->num_dsc-1; i >= 0; i--) {
+ if (update_state->pg_pipe_res_update[PG_DSC][i]) {
+ if (pg_cntl->funcs->dsc_pg_control)
+ pg_cntl->funcs->dsc_pg_control(pg_cntl, i, false);
+ }
+ }
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (!update_state->pg_pipe_res_update[PG_MPCC][i] ||
+ !update_state->pg_pipe_res_update[PG_OPP][i] ||
+ !update_state->pg_pipe_res_update[PG_OPTC][i]) {
+ block_disabled = false;
+ break;
+ }
+ }
+
+ if (block_disabled) {
+ if (pg_cntl->funcs->plane_otg_pg_control)
+ pg_cntl->funcs->plane_otg_pg_control(pg_cntl, false);
+ }
+
+ if (update_state->pg_res_update[PG_DIO]) {
+ if (pg_cntl->funcs->dio_pg_control)
+ pg_cntl->funcs->dio_pg_control(pg_cntl, false);
+ }
+
+ if (update_state->pg_res_update[PG_DCCG] &&
+ update_state->pg_res_update[PG_DCIO] &&
+ update_state->pg_res_update[PG_DCOH]) {
+ // Driver PG should not power down DCCG, DCIO, DCOH. This is handled by IPS.
+ if (pg_cntl->funcs->io_clk_pg_control)
+ pg_cntl->funcs->io_clk_pg_control(pg_cntl, false);
+ }
+}
+
+/**
+ * dcn42_hw_block_power_up() - power up sequence
+ *
+ * The following sequence describes the ON-OFF (ONO) for power up:
+ *
+ * ONO Region 0, DCPG 22: dccg dcio dcoh
+ * ONO Region 1, DCPG 26: dio
+ * ONO Region 3, DCPG 24: mpc, opp, optc, dwb
+ * ONO Region 6, DCPG 16: dsc0
+ * ONO Region 8, DCPG 17: dsc1
+ * ONO Region 10, DCPG 18: dsc2
+ * ONO Region 12, DCPG 19: dsc3
+ * ONO Region 2, DCPG 23: dchubbub, dchububmem, dchvm
+ * ONO Region 5, DCPG 0: dchubp0, dpp0
+ * ONO Region 7, DCPG 1: dchubp1, dpp1
+ * ONO Region 9, DCPG 2: dchubp2, dpp2
+ * ONO Region 11, DCPG 3: dchubp3, dpp3
+ * ONO Region 4, DCPG 25: hpo
+ *
+ * No sequential power up/down ordering for DCN42
+ *
+ * @dc: Current DC state
+ * @update_state: update PG sequence states for HW block
+ */
+void dcn42_hw_block_power_up(struct dc *dc,
+ struct pg_block_update *update_state)
+{
+ int i = 0;
+ struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl;
+ bool block_enabled = false;
+
+ if (!pg_cntl)
+ return;
+ if (dc->debug.ignore_pg)
+ return;
+
+ if (update_state->pg_res_update[PG_DCCG] ||
+ update_state->pg_res_update[PG_DCIO] ||
+ update_state->pg_res_update[PG_DCOH]) {
+ if (pg_cntl->funcs->io_clk_pg_control)
+ pg_cntl->funcs->io_clk_pg_control(pg_cntl, true);
+ }
+
+ if (update_state->pg_res_update[PG_DIO]) {
+ if (pg_cntl->funcs->dio_pg_control)
+ pg_cntl->funcs->dio_pg_control(pg_cntl, true);
+ }
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (update_state->pg_pipe_res_update[PG_MPCC][i] ||
+ update_state->pg_pipe_res_update[PG_OPP][i] ||
+ update_state->pg_pipe_res_update[PG_OPTC][i]) {
+ block_enabled = true;
+ break;
+ }
+ }
+ if (block_enabled) {
+ if (pg_cntl->funcs->plane_otg_pg_control)
+ pg_cntl->funcs->plane_otg_pg_control(pg_cntl, true);
+ }
+
+ for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
+ if (update_state->pg_pipe_res_update[PG_DSC][i]) {
+ if (pg_cntl->funcs->dsc_pg_control)
+ pg_cntl->funcs->dsc_pg_control(pg_cntl, i, true);
+ }
+ }
+
+ if (update_state->pg_res_update[PG_DCHUBBUB]) {
+ if (pg_cntl->funcs->mem_pg_control)
+ pg_cntl->funcs->mem_pg_control(pg_cntl, true);
+ }
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
+ update_state->pg_pipe_res_update[PG_DPP][i]) {
+ if (pg_cntl->funcs->hubp_dpp_pg_control)
+ pg_cntl->funcs->hubp_dpp_pg_control(pg_cntl, i, true);
+ }
+ }
+ if (update_state->pg_res_update[PG_HPO]) {
+ if (pg_cntl->funcs->hpo_pg_control)
+ pg_cntl->funcs->hpo_pg_control(pg_cntl, true);
+ }
+}
+void dcn42_root_clock_control(struct dc *dc,
+ struct pg_block_update *update_state, bool power_on)
+{
+ int i = 0;
+ struct pg_cntl *pg_cntl = dc->res_pool->pg_cntl;
+
+ if (!pg_cntl)
+ return;
+ /*enable root clock first when power up*/
+ if (power_on) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
+ update_state->pg_pipe_res_update[PG_DPP][i]) {
+ if (dc->hwseq->funcs.dpp_root_clock_control)
+ dc->hwseq->funcs.dpp_root_clock_control(dc->hwseq, i, power_on);
+ }
+ if (update_state->pg_pipe_res_update[PG_DPSTREAM][i])
+ if (dc->hwseq->funcs.dpstream_root_clock_control)
+ dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on);
+ }
+
+ for (i = 0; i < dc->res_pool->dig_link_enc_count; i++)
+ if (update_state->pg_pipe_res_update[PG_PHYSYMCLK][i])
+ if (dc->hwseq->funcs.physymclk_root_clock_control)
+ dc->hwseq->funcs.physymclk_root_clock_control(dc->hwseq, i, power_on);
+
+ }
+ for (i = 0; i < dc->res_pool->res_cap->num_dsc; i++) {
+ if (update_state->pg_pipe_res_update[PG_DSC][i]) {
+ if (power_on) {
+ if (dc->res_pool->dccg->funcs->enable_dsc)
+ dc->res_pool->dccg->funcs->enable_dsc(dc->res_pool->dccg, i);
+ } else {
+ if (dc->res_pool->dccg->funcs->disable_dsc)
+ dc->res_pool->dccg->funcs->disable_dsc(dc->res_pool->dccg, i);
+ }
+ }
+ }
+ /*disable root clock first when power down*/
+ if (!power_on) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (update_state->pg_pipe_res_update[PG_HUBP][i] &&
+ update_state->pg_pipe_res_update[PG_DPP][i]) {
+ if (dc->hwseq->funcs.dpp_root_clock_control)
+ dc->hwseq->funcs.dpp_root_clock_control(dc->hwseq, i, power_on);
+ }
+ if (update_state->pg_pipe_res_update[PG_DPSTREAM][i])
+ if (dc->hwseq->funcs.dpstream_root_clock_control)
+ dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on);
+ }
+
+ for (i = 0; i < dc->res_pool->dig_link_enc_count; i++)
+ if (update_state->pg_pipe_res_update[PG_PHYSYMCLK][i])
+ if (dc->hwseq->funcs.physymclk_root_clock_control)
+ dc->hwseq->funcs.physymclk_root_clock_control(dc->hwseq, i, power_on);
+
+ }
+}
+void dcn42_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc)
+{
+ (void)dc;
+ struct crtc_stereo_flags flags = { 0 };
+ struct dc_stream_state *stream = pipe_ctx->stream;
+
+ dcn10_config_stereo_parameters(stream, &flags);
+
+ pipe_ctx->stream_res.opp->funcs->opp_program_stereo(
+ pipe_ctx->stream_res.opp,
+ flags.PROGRAM_STEREO == 1,
+ &stream->timing);
+
+ pipe_ctx->stream_res.tg->funcs->program_stereo(
+ pipe_ctx->stream_res.tg,
+ &stream->timing,
+ &flags);
+
+ return;
+}
+void dcn42_dmub_hw_control_lock(struct dc *dc, struct dc_state *context, bool lock)
+{
+
+ union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
+
+ if (!dc->ctx || !dc->ctx->dmub_srv)
+ return;
+
+ /* Use helper to check PSR/Replay for all streams in context */
+
+ if (!dc->debug.fams2_config.bits.enable && !dc_dmub_srv_is_cursor_offload_enabled(dc)
+ && !dmub_hw_lock_mgr_does_context_require_lock(dc, context))
+ return;
+
+ hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
+ hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
+ hw_lock_cmd.bits.lock = lock;
+ hw_lock_cmd.bits.should_release = !lock;
+ dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
+}
+
+void dcn42_dmub_hw_control_lock_fast(union block_sequence_params *params)
+{
+ struct dc *dc = params->dmub_hw_control_lock_fast_params.dc;
+ bool lock = params->dmub_hw_control_lock_fast_params.lock;
+
+ /* Use helper to check PSR/Replay for the given stream in fast path */
+ if (params->dmub_hw_control_lock_fast_params.is_required) {
+ union dmub_inbox0_cmd_lock_hw hw_lock_cmd = { 0 };
+ hw_lock_cmd.bits.command_code = DMUB_INBOX0_CMD__HW_LOCK;
+ hw_lock_cmd.bits.hw_lock_client = HW_LOCK_CLIENT_DRIVER;
+ hw_lock_cmd.bits.lock = lock;
+ hw_lock_cmd.bits.should_release = !lock;
+ dmub_hw_lock_mgr_inbox0_cmd(dc->ctx->dmub_srv, hw_lock_cmd);
+ }
+}
+
+/* In headless boot cases, DIG may be turned
+ * on which causes HW/SW discrepancies.
+ * To avoid this, power down hardware on boot
+ * if DIG is turned on
+ */
+void dcn42_power_down_on_boot(struct dc *dc)
+{
+ struct dc_link *edp_links[MAX_NUM_EDP];
+ struct dc_link *edp_link = NULL;
+ unsigned int edp_num;
+ int i = 0;
+
+ dc_get_edp_links(dc, edp_links, &edp_num);
+ if (edp_num)
+ edp_link = edp_links[0];
+
+ if (edp_link && edp_link->link_enc->funcs->is_dig_enabled &&
+ edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) &&
+ dc->hwseq->funcs.edp_backlight_control &&
+ dc->hwseq->funcs.power_down &&
+ dc->hwss.edp_power_control) {
+ dc->hwseq->funcs.edp_backlight_control(edp_link, false);
+ dc->hwseq->funcs.power_down(dc);
+ dc->hwss.edp_power_control(edp_link, false);
+ } else {
+ for (i = 0; i < dc->link_count; i++) {
+ struct dc_link *link = dc->links[i];
+
+ if (link->link_enc && link->link_enc->funcs->is_dig_enabled &&
+ link->link_enc->funcs->is_dig_enabled(link->link_enc) &&
+ dc->hwseq->funcs.power_down) {
+ dc->hwseq->funcs.power_down(dc);
+ break;
+ }
+
+ }
+ }
+
+ /*
+ * Call update_clocks with empty context
+ * to send DISPLAY_OFF
+ * Otherwise DISPLAY_OFF may not be asserted
+ */
+ if (dc->clk_mgr->funcs->set_low_power_state)
+ dc->clk_mgr->funcs->set_low_power_state(dc->clk_mgr);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h
new file mode 100644
index 000000000000..c4cfeed45b19
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_hwseq.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2026 Advanced Micro Devices, Inc. */
+
+#ifndef __DC_HWSS_DCN42_H__
+#define __DC_HWSS_DCN42_H__
+
+#include "dc.h"
+#include "hw_sequencer_private.h"
+
+void dcn42_init_hw(struct dc *dc);
+void dcn42_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx);
+
+void dcn42_program_cm_hist(
+ struct dc *dc,
+ struct pipe_ctx *pipe_ctx,
+ const struct dc_plane_state *plane_state);
+
+bool dcn42_set_mcm_luts(struct pipe_ctx *pipe_ctx,
+ const struct dc_plane_state *plane_state);
+
+bool dcn42_program_rmcm_luts(
+ struct hubp *hubp,
+ struct pipe_ctx *pipe_ctx,
+ const struct dc_plane_cm *cm,
+ struct mpc *mpc,
+ int mpcc_id);
+void dcn42_hardware_release(struct dc *dc);
+
+void dcn42_prepare_bandwidth(
+ struct dc *dc,
+ struct dc_state *context);
+void dcn42_optimize_bandwidth(struct dc *dc, struct dc_state *context);
+void dcn42_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,
+ struct pg_block_update *update_state);
+void dcn42_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context,
+ struct pg_block_update *update_state);
+void dcn42_hw_block_power_down(struct dc *dc,
+ struct pg_block_update *update_state);
+void dcn42_hw_block_power_up(struct dc *dc,
+ struct pg_block_update *update_state);
+void dcn42_root_clock_control(struct dc *dc,
+ struct pg_block_update *update_state, bool power_on);
+void dcn42_dmub_hw_control_lock(struct dc *dc, struct dc_state *context, bool lock);
+void dcn42_dmub_hw_control_lock_fast(union block_sequence_params *params);
+void dcn42_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc);
+void dcn42_power_down_on_boot(struct dc *dc);
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c
new file mode 100644
index 000000000000..b324a2195e8a
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dce110/dce110_hwseq.h"
+#include "dcn10/dcn10_hwseq.h"
+#include "dcn20/dcn20_hwseq.h"
+#include "dcn21/dcn21_hwseq.h"
+#include "dcn30/dcn30_hwseq.h"
+#include "dcn31/dcn31_hwseq.h"
+#include "dcn32/dcn32_hwseq.h"
+#include "dcn314/dcn314_hwseq.h"
+#include "dcn35/dcn35_hwseq.h"
+#include "dcn401/dcn401_hwseq.h"
+#include "dcn42/dcn42_hwseq.h"
+#include "dcn42_init.h"
+
+static const struct hw_sequencer_funcs dcn42_funcs = {
+ .program_gamut_remap = dcn401_program_gamut_remap,
+ .init_hw = dcn42_init_hw,
+ .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
+ .power_down_on_boot = dcn42_power_down_on_boot,
+ .apply_ctx_for_surface = NULL,
+ .program_front_end_for_ctx = dcn401_program_front_end_for_ctx,
+ .clear_surface_dcc_and_tiling = dcn10_reset_surface_dcc_and_tiling,
+ .wait_for_pending_cleared = dcn10_wait_for_pending_cleared,
+ .post_unlock_program_front_end = dcn401_post_unlock_program_front_end,
+ .update_plane_addr = dcn20_update_plane_addr,
+ .update_dchub = dcn10_update_dchub,
+ .update_pending_status = dcn10_update_pending_status,
+ .program_output_csc = dcn20_program_output_csc,
+ .trigger_3dlut_dma_load = dcn401_trigger_3dlut_dma_load,
+ .enable_accelerated_mode = dce110_enable_accelerated_mode,
+ .enable_timing_synchronization = dcn10_enable_timing_synchronization,
+ .enable_per_frame_crtc_position_reset = dcn10_enable_per_frame_crtc_position_reset,
+ .update_info_frame = dcn31_update_info_frame,
+ .send_immediate_sdp_message = dcn10_send_immediate_sdp_message,
+ .enable_stream = dcn401_enable_stream,
+ .disable_stream = dce110_disable_stream,
+ .unblank_stream = dcn401_unblank_stream,
+ .blank_stream = dce110_blank_stream,
+ .enable_audio_stream = dce110_enable_audio_stream,
+ .disable_audio_stream = dce110_disable_audio_stream,
+ .disable_plane = dcn35_disable_plane,
+ .pipe_control_lock = dcn20_pipe_control_lock,
+ .interdependent_update_lock = dcn401_interdependent_update_lock,
+ .cursor_lock = dcn10_cursor_lock,
+ .prepare_bandwidth = dcn42_prepare_bandwidth,
+ .optimize_bandwidth = dcn42_optimize_bandwidth,
+ .update_bandwidth = dcn401_update_bandwidth,
+ .set_drr = dcn35_set_drr,
+ .get_position = dcn10_get_position,
+ .set_static_screen_control = dcn35_set_static_screen_control,
+ .setup_stereo = dcn42_setup_stereo,
+ .set_avmute = dcn30_set_avmute,
+ .log_hw_state = dcn10_log_hw_state,
+ .get_hw_state = dcn10_get_hw_state,
+ .clear_status_bits = dcn10_clear_status_bits,
+ .wait_for_mpcc_disconnect = dcn10_wait_for_mpcc_disconnect,
+ .edp_backlight_control = dce110_edp_backlight_control,
+ .edp_power_control = dce110_edp_power_control,
+ .edp_wait_for_hpd_ready = dce110_edp_wait_for_hpd_ready,
+ .edp_wait_for_T12 = dce110_edp_wait_for_T12,
+ .set_cursor_position = dcn401_set_cursor_position,
+ .set_cursor_attribute = dcn10_set_cursor_attribute,
+ .set_cursor_sdr_white_level = dcn10_set_cursor_sdr_white_level,
+ .abort_cursor_offload_update = dcn35_abort_cursor_offload_update,
+ .begin_cursor_offload_update = dcn35_begin_cursor_offload_update,
+ .commit_cursor_offload_update = dcn35_commit_cursor_offload_update,
+ .update_cursor_offload_pipe = dcn401_update_cursor_offload_pipe,
+ .notify_cursor_offload_drr_update = dcn35_notify_cursor_offload_drr_update,
+ .program_cursor_offload_now = dcn35_program_cursor_offload_now,
+ .setup_periodic_interrupt = dcn10_setup_periodic_interrupt,
+ .set_clock = dcn10_set_clock,
+ .get_clock = dcn10_get_clock,
+ .program_triplebuffer = dcn20_program_triple_buffer,
+ .enable_writeback = dcn30_enable_writeback,
+ .disable_writeback = dcn30_disable_writeback,
+ .update_writeback = dcn30_update_writeback,
+ .dmdata_status_done = dcn20_dmdata_status_done,
+ .program_dmdata_engine = dcn30_program_dmdata_engine,
+ .set_dmdata_attributes = dcn20_set_dmdata_attributes,
+ .init_sys_ctx = dcn31_init_sys_ctx,
+ .init_vm_ctx = dcn20_init_vm_ctx,
+ .set_flip_control_gsl = dcn20_set_flip_control_gsl,
+ .get_vupdate_offset_from_vsync = dcn10_get_vupdate_offset_from_vsync,
+ .calc_vupdate_position = dcn10_calc_vupdate_position,
+ .apply_idle_power_optimizations = dcn35_apply_idle_power_optimizations,
+ .does_plane_fit_in_mall = NULL,
+ .set_backlight_level = dcn31_set_backlight_level,
+ .set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
+ .hardware_release = dcn42_hardware_release,
+ .set_pipe = dcn21_set_pipe,
+ .enable_lvds_link_output = dce110_enable_lvds_link_output,
+ .enable_tmds_link_output = dce110_enable_tmds_link_output,
+ .enable_dp_link_output = dce110_enable_dp_link_output,
+ .disable_link_output = dcn401_disable_link_output,
+ .set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
+ .optimize_pwr_state = dcn21_optimize_pwr_state,
+ .exit_optimized_pwr_state = dcn21_exit_optimized_pwr_state,
+ .get_dcc_en_bits = dcn10_get_dcc_en_bits,
+ .enable_phantom_streams = dcn32_enable_phantom_streams,
+ .disable_phantom_streams = dcn32_disable_phantom_streams,
+ .update_visual_confirm_color = dcn10_update_visual_confirm_color,
+ .update_phantom_vp_position = dcn32_update_phantom_vp_position,
+ .apply_update_flags_for_phantom = dcn32_apply_update_flags_for_phantom,
+ .wait_for_dcc_meta_propagation = dcn401_wait_for_dcc_meta_propagation,
+ .is_pipe_topology_transition_seamless = dcn32_is_pipe_topology_transition_seamless,
+ .dmub_hw_control_lock = dcn42_dmub_hw_control_lock,
+ .fams2_update_config = dcn401_fams2_update_config,
+ .dmub_hw_control_lock_fast = dcn42_dmub_hw_control_lock_fast,
+ .program_outstanding_updates = dcn401_program_outstanding_updates,
+ .wait_for_all_pending_updates = dcn30_wait_for_all_pending_updates,
+ .detect_pipe_changes = dcn401_detect_pipe_changes,
+ .enable_plane = dcn35_enable_plane,
+ .update_dchubp_dpp = dcn20_update_dchubp_dpp,
+ .post_unlock_reset_opp = dcn20_post_unlock_reset_opp,
+ .get_underflow_debug_data = dcn30_get_underflow_debug_data,
+ // Driver PG
+ .hw_block_power_up = dcn42_hw_block_power_up,
+ .hw_block_power_down = dcn42_hw_block_power_down,
+ .root_clock_control = dcn42_root_clock_control,
+ .calc_blocks_to_gate = dcn42_calc_blocks_to_gate,
+ .calc_blocks_to_ungate = dcn42_calc_blocks_to_ungate,
+
+};
+
+static const struct hwseq_private_funcs dcn42_private_funcs = {
+ .init_pipes = dcn35_init_pipes,
+ .plane_atomic_disconnect = dcn10_plane_atomic_disconnect,
+ .update_mpcc = dcn42_update_mpcc,
+ .set_input_transfer_func = dcn32_set_input_transfer_func,
+ .set_output_transfer_func = dcn401_set_output_transfer_func,
+ .power_down = dce110_power_down,
+ .enable_display_power_gating = dcn10_dummy_display_power_gating,
+ .blank_pixel_data = dcn20_blank_pixel_data,
+ .reset_hw_ctx_wrap = dcn401_reset_hw_ctx_wrap,
+ .enable_stream_timing = dcn401_enable_stream_timing,
+ .edp_backlight_control = dce110_edp_backlight_control,
+ .setup_vupdate_interrupt = dcn20_setup_vupdate_interrupt,
+ .did_underflow_occur = dcn10_did_underflow_occur,
+ .init_blank = dcn32_init_blank,
+ .disable_vga = dcn20_disable_vga,
+ .bios_golden_init = dcn10_bios_golden_init,
+ .plane_atomic_disable = dcn35_plane_atomic_disable,
+ .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree,
+ .update_odm = dcn401_update_odm,
+ .dsc_pg_status = dcn32_dsc_pg_status,
+ .set_hdr_multiplier = dcn10_set_hdr_multiplier,
+ .wait_for_blank_complete = dcn20_wait_for_blank_complete,
+ .set_mcm_luts = dcn42_set_mcm_luts,
+ .program_mall_pipe_config = dcn32_program_mall_pipe_config,
+ .update_mall_sel = dcn32_update_mall_sel,
+ .calculate_dccg_k1_k2_values = NULL,
+ .apply_single_controller_ctx_to_hw = dce110_apply_single_controller_ctx_to_hw,
+ .reset_back_end_for_pipe = dcn401_reset_back_end_for_pipe,
+ .populate_mcm_luts = NULL,
+ .perform_3dlut_wa_unlock = dcn401_perform_3dlut_wa_unlock,
+ .program_cm_hist = dcn42_program_cm_hist,
+ .dpp_root_clock_control = dcn35_dpp_root_clock_control,
+ .dpstream_root_clock_control = dcn35_dpstream_root_clock_control,
+ .physymclk_root_clock_control = dcn35_physymclk_root_clock_control,
+ .resync_fifo_dccg_dio = dcn314_resync_fifo_dccg_dio,
+ .wait_for_pipe_update_if_needed = dcn10_wait_for_pipe_update_if_needed,
+ .set_wait_for_update_needed_for_pipe = dcn10_set_wait_for_update_needed_for_pipe,
+};
+
+void dcn42_hw_sequencer_init_functions(struct dc *dc)
+{
+ dc->hwss = dcn42_funcs;
+ dc->hwseq->funcs = dcn42_private_funcs;
+
+}
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.h
new file mode 100644
index 000000000000..f66eb752eeeb
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn42/dcn42_init.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2026 Advanced Micro Devices, Inc. */
+
+#ifndef __DC_DCN42_INIT_H__
+#define __DC_DCN42_INIT_H__
+
+struct dc;
+
+void dcn42_hw_sequencer_init_functions(struct dc *dc);
+
+#endif /* __DC_DCN401_INIT_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
index 4632a5761b16..d1dba7ffcd9b 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Advanced Micro Devices, Inc.
+ * Copyright 2015-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -174,6 +174,12 @@ struct program_mcache_id_and_split_coordinate {
struct dml2_hubp_pipe_mcache_regs *mcache_regs;
};
+struct control_cm_hist_params {
+ struct dpp *dpp;
+ struct cm_hist_control cm_hist_control;
+ enum dc_color_space color_space;
+};
+
struct program_cursor_update_now_params {
struct dc *dc;
struct pipe_ctx *pipe_ctx;
@@ -755,6 +761,7 @@ union block_sequence_params {
struct dmub_hw_control_lock_fast_params dmub_hw_control_lock_fast_params;
struct program_surface_config_params program_surface_config_params;
struct program_mcache_id_and_split_coordinate program_mcache_id_and_split_coordinate;
+ struct control_cm_hist_params control_cm_hist_params;
struct program_cursor_update_now_params program_cursor_update_now_params;
struct hubp_wait_pipe_read_start_params hubp_wait_pipe_read_start_params;
struct apply_update_flags_for_phantom_params apply_update_flags_for_phantom_params;
@@ -879,6 +886,7 @@ enum block_sequence_func {
DMUB_HW_CONTROL_LOCK_FAST,
HUBP_PROGRAM_SURFACE_CONFIG,
HUBP_PROGRAM_MCACHE_ID,
+ DPP_PROGRAM_CM_HIST,
PROGRAM_CURSOR_UPDATE_NOW,
HUBP_WAIT_PIPE_READ_START,
HWS_APPLY_UPDATE_FLAGS_FOR_PHANTOM,
@@ -1189,6 +1197,8 @@ struct hw_sequencer_funcs {
void (*disable_link_output)(struct dc_link *link,
const struct link_resource *link_res,
enum signal_type signal);
+ bool (*dac_load_detect)(struct dc_link *link);
+ void (*prepare_ddc)(struct dc_link *link);
void (*get_dcc_en_bits)(struct dc *dc, int *dcc_en_bits);
@@ -1355,6 +1365,10 @@ void get_dcc_visual_confirm_color(
struct pipe_ctx *pipe_ctx,
struct tg_color *color);
+void get_refresh_rate_confirm_color(
+ struct pipe_ctx *pipe_ctx,
+ struct tg_color *color);
+
void set_p_state_switch_method(
struct dc *dc,
struct dc_state *context,
@@ -1413,6 +1427,8 @@ void hwss_program_surface_config(union block_sequence_params *params);
void hwss_program_mcache_id_and_split_coordinate(union block_sequence_params *params);
+void hwss_program_cm_hist(union block_sequence_params *params);
+
void hwss_set_odm_combine(union block_sequence_params *params);
void hwss_set_odm_bypass(union block_sequence_params *params);
@@ -1763,6 +1779,11 @@ void hwss_add_opp_program_bit_depth_reduction(struct block_sequence_state *seq_s
bool use_default_params,
struct pipe_ctx *pipe_ctx);
+void hwss_add_dpp_program_cm_hist(struct block_sequence_state *seq_state,
+ struct dpp *dpp,
+ struct cm_hist_control cm_hist_control,
+ enum dc_color_space color_space);
+
void hwss_add_dc_ip_request_cntl(struct block_sequence_state *seq_state,
struct dc *dc,
bool enable);
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 406db231bc72..8e3f54fb53fd 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Advanced Micro Devices, Inc.
+ * Copyright 2015-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -222,6 +222,9 @@ struct hwseq_private_funcs {
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);
void (*dc_ip_request_cntl)(struct dc *dc, bool enable);
+ void (*program_cm_hist)(struct dc *dc,
+ struct pipe_ctx *pipe_ctx,
+ const struct dc_plane_state *plane_state);
};
struct dce_hwseq {
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 43579b0e1482..e960ca9062ad 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -214,6 +214,7 @@ struct resource_funcs {
unsigned int index);
void (*get_panel_config_defaults)(struct dc_panel_config *panel_config);
+ void (*get_default_tiling_info)(struct dc_tiling_info *tiling_info);
void (*build_pipe_pix_clk_params)(struct pipe_ctx *pipe_ctx);
/*
* Get indicator of power from a context that went through full validation
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 2c9a4a12bd8a..21224fd6b36d 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
@@ -1,5 +1,6 @@
+/* SPDX-License-Identifier: MIT */
/*
- * Copyright 2012-16 Advanced Micro Devices, Inc.
+ * Copyright 2012-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -95,6 +96,26 @@ struct dcn301_clk_internal {
uint32_t CLK1_CLK3_BYPASS_CNTL; //dcfclk bypass
};
+struct dcn42_clk_internal {
+ int dummy;
+ uint32_t CLK8_CLK0_CURRENT_CNT; //dispclk
+ uint32_t CLK8_CLK1_CURRENT_CNT; //dppclk
+ uint32_t CLK8_CLK2_CURRENT_CNT; //dprefclk
+ uint32_t CLK8_CLK3_CURRENT_CNT; //dcfclk
+ uint32_t CLK8_CLK4_CURRENT_CNT; //dtbclk
+ uint32_t CLK8_CLK0_DS_CNTL; //dispclk deep_sleep_divider
+ uint32_t CLK8_CLK1_DS_CNTL; //dppclk deep_sleep_divider
+ uint32_t CLK8_CLK2_DS_CNTL; //dprefclk deep_sleep_divider
+ uint32_t CLK8_CLK3_DS_CNTL; //dcfclk deep_sleep_divider
+ uint32_t CLK8_CLK4_DS_CNTL; //dtbclk deep_sleep_divider
+ uint32_t CLK8_CLK0_BYPASS_CNTL; //dispclk bypass
+ uint32_t CLK8_CLK1_BYPASS_CNTL; //dppclk bypass
+ uint32_t CLK8_CLK2_BYPASS_CNTL; //dprefclk bypass
+ uint32_t CLK8_CLK3_BYPASS_CNTL; //dcfclk bypass
+ uint32_t CLK8_CLK4_BYPASS_CNTL; //dtbclk bypass
+ uint32_t CLK8_CLK_TICK_CNT__TIMER_THRESHOLD;
+};
+
/* Will these bw structures be ASIC specific? */
#define MAX_NUM_DPM_LVL 8
@@ -194,6 +215,7 @@ struct clk_state_registers_and_bypass {
uint32_t dcfclk_bypass;
uint32_t dprefclk_bypass;
uint32_t dispclk_bypass;
+ uint32_t timer_threshold;
};
struct rv1_clk_internal {
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 bac8febad69a..c69ccfcebeb5 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
@@ -1,5 +1,6 @@
+/* SPDX-License-Identifier: MIT */
/*
- * Copyright 2018 Advanced Micro Devices, Inc.
+ * Copyright 2018-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -89,11 +90,6 @@ enum dentist_divider_range {
.DPREFCLK_CNTL = mmDPREFCLK_CNTL, \
.DENTIST_DISPCLK_CNTL = mmDENTIST_DISPCLK_CNTL
-#if defined(CONFIG_DRM_AMD_DC_SI)
-#define CLK_COMMON_REG_LIST_DCE60_BASE() \
- SR(DENTIST_DISPCLK_CNTL)
-#endif
-
#define CLK_COMMON_REG_LIST_DCN_BASE() \
SR(DENTIST_DISPCLK_CNTL)
@@ -119,12 +115,6 @@ enum dentist_divider_range {
CLK_SF(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, mask_sh), \
CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, mask_sh)
-#if defined(CONFIG_DRM_AMD_DC_SI)
-#define CLK_COMMON_MASK_SH_LIST_DCE60_COMMON_BASE(mask_sh) \
- CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\
- CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh)
-#endif
-
#define CLK_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(mask_sh) \
CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\
CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh)
@@ -234,6 +224,45 @@ enum dentist_divider_range {
#define CLK_COMMON_MASK_SH_LIST_DCN401(mask_sh) \
CLK_COMMON_MASK_SH_LIST_DCN321(mask_sh)
+#define CLK_REG_LIST_DCN42() \
+ SR(DENTIST_DISPCLK_CNTL), \
+ CLK_SR_DCN42(CLK8_CLK_TICK_CNT_CONFIG_REG), \
+ CLK_SR_DCN42(CLK8_CLK0_CURRENT_CNT), \
+ CLK_SR_DCN42(CLK8_CLK1_CURRENT_CNT), \
+ CLK_SR_DCN42(CLK8_CLK2_CURRENT_CNT), \
+ CLK_SR_DCN42(CLK8_CLK3_CURRENT_CNT), \
+ CLK_SR_DCN42(CLK8_CLK4_CURRENT_CNT), \
+ CLK_SR_DCN42(CLK8_CLK0_BYPASS_CNTL), \
+ CLK_SR_DCN42(CLK8_CLK1_BYPASS_CNTL), \
+ CLK_SR_DCN42(CLK8_CLK2_BYPASS_CNTL), \
+ CLK_SR_DCN42(CLK8_CLK3_BYPASS_CNTL), \
+ CLK_SR_DCN42(CLK8_CLK4_BYPASS_CNTL), \
+ CLK_SR_DCN42(CLK8_CLK0_DS_CNTL), \
+ CLK_SR_DCN42(CLK8_CLK1_DS_CNTL), \
+ CLK_SR_DCN42(CLK8_CLK2_DS_CNTL), \
+ CLK_SR_DCN42(CLK8_CLK3_DS_CNTL), \
+ CLK_SR_DCN42(CLK8_CLK4_DS_CNTL)
+
+#define CLK_COMMON_MASK_SH_LIST_DCN42(mask_sh) \
+ CLK_SF(CLK8_CLK_TICK_CNT_CONFIG_REG, TIMER_THRESHOLD, mask_sh), \
+ CLK_SF(CLK8_CLK0_BYPASS_CNTL, CLK0_BYPASS_SEL, mask_sh), \
+ CLK_SF(CLK8_CLK1_BYPASS_CNTL, CLK1_BYPASS_SEL, mask_sh), \
+ CLK_SF(CLK8_CLK2_BYPASS_CNTL, CLK2_BYPASS_SEL, mask_sh), \
+ CLK_SF(CLK8_CLK3_BYPASS_CNTL, CLK3_BYPASS_SEL, mask_sh), \
+ CLK_SF(CLK8_CLK4_BYPASS_CNTL, CLK4_BYPASS_SEL, mask_sh), \
+ CLK_SF(CLK8_CLK0_DS_CNTL, CLK0_DS_DIV_ID, mask_sh), \
+ CLK_SF(CLK8_CLK1_DS_CNTL, CLK1_DS_DIV_ID, mask_sh), \
+ CLK_SF(CLK8_CLK2_DS_CNTL, CLK2_DS_DIV_ID, mask_sh), \
+ CLK_SF(CLK8_CLK3_DS_CNTL, CLK3_DS_DIV_ID, mask_sh), \
+ CLK_SF(CLK8_CLK4_DS_CNTL, CLK4_DS_DIV_ID, mask_sh), \
+ CLK_SF(CLK8_CLK0_DS_CNTL, CLK0_ALLOW_DS, mask_sh), \
+ CLK_SF(CLK8_CLK1_DS_CNTL, CLK1_ALLOW_DS, mask_sh), \
+ CLK_SF(CLK8_CLK2_DS_CNTL, CLK2_ALLOW_DS, mask_sh), \
+ CLK_SF(CLK8_CLK3_DS_CNTL, CLK3_ALLOW_DS, mask_sh), \
+ CLK_SF(CLK8_CLK4_DS_CNTL, CLK4_ALLOW_DS, mask_sh), \
+
+
+
#define CLK_REG_FIELD_LIST(type) \
type DPREFCLK_SRC_SEL; \
type DENTIST_DPREFCLK_WDIVIDER; \
@@ -246,6 +275,42 @@ enum dentist_divider_range {
type FbMult_int; \
type FbMult_frac;
+#define CLK42_REG_LIST(clkip_num, type) \
+ type CLK ## clkip_num ## _CLK_TICK_CNT_CONFIG_REG; \
+ type CLK ## clkip_num ## _CLK0_CURRENT_CNT; \
+ type CLK ## clkip_num ## _CLK1_CURRENT_CNT; \
+ type CLK ## clkip_num ## _CLK2_CURRENT_CNT; \
+ type CLK ## clkip_num ## _CLK3_CURRENT_CNT; \
+ type CLK ## clkip_num ## _CLK4_CURRENT_CNT; \
+ type CLK ## clkip_num ## _CLK0_BYPASS_CNTL; \
+ type CLK ## clkip_num ## _CLK1_BYPASS_CNTL; \
+ type CLK ## clkip_num ## _CLK2_BYPASS_CNTL; \
+ type CLK ## clkip_num ## _CLK3_BYPASS_CNTL; \
+ type CLK ## clkip_num ## _CLK4_BYPASS_CNTL; \
+ type CLK ## clkip_num ## _CLK0_DS_CNTL; \
+ type CLK ## clkip_num ## _CLK1_DS_CNTL; \
+ type CLK ## clkip_num ## _CLK2_DS_CNTL; \
+ type CLK ## clkip_num ## _CLK3_DS_CNTL; \
+ type CLK ## clkip_num ## _CLK4_DS_CNTL;
+
+#define CLK42_REG_FIELD_LIST(type) \
+ type TIMER_THRESHOLD; \
+ type CLK0_BYPASS_SEL; \
+ type CLK1_BYPASS_SEL; \
+ type CLK2_BYPASS_SEL; \
+ type CLK3_BYPASS_SEL; \
+ type CLK4_BYPASS_SEL; \
+ type CLK0_DS_DIV_ID; \
+ type CLK1_DS_DIV_ID; \
+ type CLK2_DS_DIV_ID; \
+ type CLK3_DS_DIV_ID; \
+ type CLK4_DS_DIV_ID; \
+ type CLK0_ALLOW_DS; \
+ type CLK1_ALLOW_DS; \
+ type CLK2_ALLOW_DS; \
+ type CLK3_ALLOW_DS; \
+ type CLK4_ALLOW_DS;
+
/*
***************************************************************************************
****************** Clock Manager Private Structures ***********************************
@@ -277,10 +342,10 @@ struct clk_mgr_registers {
uint32_t CLK2_CLK2_DFS_CNTL;
uint32_t CLK1_CLK0_CURRENT_CNT;
- uint32_t CLK1_CLK1_CURRENT_CNT;
- uint32_t CLK1_CLK2_CURRENT_CNT;
- uint32_t CLK1_CLK3_CURRENT_CNT;
- uint32_t CLK1_CLK4_CURRENT_CNT;
+ uint32_t CLK1_CLK1_CURRENT_CNT;
+ uint32_t CLK1_CLK2_CURRENT_CNT;
+ uint32_t CLK1_CLK3_CURRENT_CNT;
+ uint32_t CLK1_CLK4_CURRENT_CNT;
uint32_t CLK1_CLK5_CURRENT_CNT;
uint32_t CLK0_CLK0_DFS_CNTL;
@@ -309,16 +374,19 @@ struct clk_mgr_registers {
uint32_t CLK1_CLK5_ALLOW_DS;
uint32_t CLK5_spll_field_8;
uint32_t CLK6_spll_field_8;
+ CLK42_REG_LIST(8, uint32_t)
};
struct clk_mgr_shift {
CLK_REG_FIELD_LIST(uint8_t)
CLK20_REG_FIELD_LIST(uint8_t)
+ CLK42_REG_FIELD_LIST(uint8_t)
};
struct clk_mgr_mask {
CLK_REG_FIELD_LIST(uint32_t)
CLK20_REG_FIELD_LIST(uint32_t)
+ CLK42_REG_FIELD_LIST(uint32_t)
};
enum clock_type {
@@ -333,6 +401,8 @@ enum clock_type {
clock_type_dscclk,
clock_type_uclk,
clock_type_dramclk,
+ clock_type_dprefclk,
+ clock_type_dtbclk,
};
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 d88b57d4f512..39215ecb480e 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
+ * Copyright 2012-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -367,6 +367,14 @@ struct dpp_funcs {
void (*dpp_force_disable_cursor)(struct dpp *dpp_base);
+ void (*dpp_cm_hist_control)(
+ struct dpp *dpp_base,
+ struct cm_hist_control cm_hist_control,
+ enum dc_color_space color_space);
+
+ bool (*dpp_cm_hist_read)(
+ struct dpp *dpp_base,
+ struct cm_hist *cm_hist);
};
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 a79019365af8..2a5a81d15950 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_cm2_gpu_mem_layout 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;
@@ -243,7 +227,6 @@ struct hubp_funcs {
void (*hubp_disable_control)(struct hubp *hubp, bool disable_hubp);
unsigned int (*hubp_get_underflow_status)(struct hubp *hubp);
void (*hubp_init)(struct hubp *hubp);
-
void (*dmdata_set_attributes)(
struct hubp *hubp,
const struct dc_dmdata_attributes *attr);
@@ -290,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);
int (*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/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
index a61d12ec61bc..51581c10fd6b 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
@@ -152,6 +152,13 @@ struct dc_rgb {
uint32_t blue;
};
+struct tetrahedral_33x33x33 {
+ struct dc_rgb lut0[8985];
+ struct dc_rgb lut1[8984];
+ struct dc_rgb lut2[8984];
+ struct dc_rgb lut3[8984];
+};
+
struct tetrahedral_17x17x17 {
struct dc_rgb lut0[1229];
struct dc_rgb lut1[1228];
@@ -165,14 +172,23 @@ struct tetrahedral_9x9x9 {
struct dc_rgb lut3[182];
};
+enum lut_dimension {
+ LUT_DIM_INVALID = 0,
+ LUT_DIM_9 = 9,
+ LUT_DIM_17 = 17,
+ LUT_DIM_33 = 33,
+};
+
struct tetrahedral_params {
union {
+//TODO: Uncomment when in use.
+// struct tetrahedral_33x33x33 tetrahedral_33;
struct tetrahedral_17x17x17 tetrahedral_17;
struct tetrahedral_9x9x9 tetrahedral_9;
};
bool use_tetrahedral_9;
bool use_12bits;
-
+ enum lut_dimension lut_dim;
};
/* arr_curve_points - regamma regions/segments specification
@@ -240,7 +256,7 @@ struct default_adjustment {
enum dc_color_space out_color_space;
enum dc_color_space in_color_space;
enum dc_color_depth color_depth;
- enum pixel_format surface_pixel_format;
+ enum dc_pixel_format surface_pixel_format;
enum graphics_csc_adjust_type csc_adjust_type;
bool force_hw_default;
};
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 a8d1abe20f62..f5617674bea8 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
+ * Copyright 2012-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -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
@@ -66,7 +67,6 @@ enum mpc_output_csc_mode {
MPC_OUTPUT_CSC_COEF_B
};
-
enum mpcc_blend_mode {
MPCC_BLEND_MODE_BYPASS,
MPCC_BLEND_MODE_TOP_LAYER_PASSTHROUGH,
@@ -102,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,
@@ -117,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;
@@ -1043,6 +1036,24 @@ struct mpc_funcs {
void (*update_3dlut_fast_load_select)(struct mpc *mpc, int mpcc_id, int hubp_idx);
/**
+ * @get_3dlut_fast_load_status:
+ *
+ * Get 3D LUT fast load status and reference them with done, soft_underflow and hard_underflow pointers.
+ *
+ * Parameters:
+ * - [in/out] mpc - MPC context.
+ * - [in] mpcc_id
+ * - [in/out] done
+ * - [in/out] soft_underflow
+ * - [in/out] hard_underflow
+ *
+ * Return:
+ *
+ * void
+ */
+ void (*get_3dlut_fast_load_status)(struct mpc *mpc, int mpcc_id, uint32_t *done, uint32_t *soft_underflow, uint32_t *hard_underflow);
+
+ /**
* @populate_lut:
*
* Populate LUT with given tetrahedral parameters.
@@ -1058,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:
@@ -1070,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:
@@ -1086,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:
@@ -1125,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);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
index 671ab1fc7320..2f70bb476c97 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
+ * Copyright 2012-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -518,6 +518,8 @@ struct timing_generator_funcs {
bool (*wait_update_lock_status)(struct timing_generator *tg, bool locked);
void (*read_otg_state)(struct timing_generator *tg, struct dcn_otg_state *s);
void (*optc_read_reg_state)(struct timing_generator *tg, struct dcn_optc_reg_state *optc_reg_state);
+ void (*enable_otg_pwa)(struct timing_generator *tg, struct otc_pwa_frame_sync *pwa_param);
+ void (*disable_otg_pwa)(struct timing_generator *tg);
};
#endif
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 5a1d9b708a9d..30990355985d 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h
@@ -160,7 +160,7 @@ struct scaler_data {
struct scaling_ratios ratios;
struct scl_inits inits;
struct sharpness_adj sharpness;
- enum pixel_format format;
+ enum dc_pixel_format format;
struct line_buffer_params lb_params;
// Below struct holds the scaler values to program hw registers
struct dscl_prog_data dscl_prog_data;
diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h
index 79746d931471..cecd3282a29f 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
@@ -60,6 +60,7 @@ struct resource_caps {
int num_hpo_dp_stream_encoder;
int num_hpo_dp_link_encoder;
int num_mpc_3dlut;
+ int num_rmcm;
};
struct resource_straps {
diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile
index b5e14d792378..807b73c2a758 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile
@@ -198,3 +198,12 @@ IRQ_DCN401 = irq_service_dcn401.o
AMD_DAL_IRQ_DCN401= $(addprefix $(AMDDALPATH)/dc/irq/dcn401/,$(IRQ_DCN401))
AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCN401)
+
+###############################################################################
+# DCN 42
+###############################################################################
+IRQ_DCN42 = irq_service_dcn42.o
+
+AMD_DAL_IRQ_DCN42= $(addprefix $(AMDDALPATH)/dc/irq/dcn42/,$(IRQ_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCN42)
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
index 676df39079fc..015f3659cf77 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dce110/irq_service_dce110.c
@@ -92,7 +92,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
.enable_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\
.enable_value = {\
DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK,\
- ~DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK\
+ (uint32_t)~DC_HPD_INT_CONTROL__DC_HPD_INT_EN_MASK\
},\
.ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
.ack_mask = DC_HPD_INT_CONTROL__DC_HPD_INT_ACK_MASK,\
@@ -107,7 +107,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
.enable_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\
.enable_value = {\
DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK,\
- ~DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK },\
+ (uint32_t)~DC_HPD_INT_CONTROL__DC_HPD_RX_INT_EN_MASK },\
.ack_reg = mmHPD ## reg_num ## _DC_HPD_INT_CONTROL,\
.ack_mask = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\
.ack_value = DC_HPD_INT_CONTROL__DC_HPD_RX_INT_ACK_MASK,\
@@ -121,7 +121,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
.enable_value = {\
GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
- ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\
+ (uint32_t)~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\
.ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\
.ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
.ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
@@ -136,7 +136,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
.enable_value = {\
CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
- ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\
+ (uint32_t)~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\
.ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\
.ack_mask =\
CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\
@@ -152,7 +152,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
.enable_value = {\
CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
- ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\
+ (uint32_t)~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\
.ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\
.ack_mask =\
CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\
@@ -183,6 +183,7 @@ bool dal_irq_service_dummy_set(struct irq_service *irq_service,
const struct irq_source_info *info,
bool enable)
{
+ (void)enable;
DC_LOG_ERROR("%s: called for non-implemented irq source, src_id=%u, ext_id=%u\n",
__func__, info->src_id, info->ext_id);
@@ -328,6 +329,7 @@ enum dc_irq_source to_dal_irq_source_dce110(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
switch (src_id) {
case VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0:
return DC_IRQ_SOURCE_VBLANK1;
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c
index b473dae2abbb..dbab6e3737a1 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dce120/irq_service_dce120.c
@@ -79,7 +79,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c
index b5c5f42cf8f2..3e19dfdd0474 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dce80/irq_service_dce80.c
@@ -68,7 +68,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
.enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\
.enable_value = {\
DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK,\
- ~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK\
+ (uint32_t)~DC_HPD1_INT_CONTROL__DC_HPD1_INT_EN_MASK\
},\
.ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\
.ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_INT_ACK_MASK,\
@@ -83,7 +83,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
.enable_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\
.enable_value = {\
DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK,\
- ~DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK },\
+ (uint32_t)~DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_EN_MASK },\
.ack_reg = mmDC_HPD ## reg_num ## _INT_CONTROL,\
.ack_mask = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\
.ack_value = DC_HPD1_INT_CONTROL__DC_HPD1_RX_INT_ACK_MASK,\
@@ -98,7 +98,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
.enable_value = {\
GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK,\
- ~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\
+ (uint32_t)~GRPH_INTERRUPT_CONTROL__GRPH_PFLIP_INT_MASK_MASK},\
.ack_reg = mmDCP ## reg_num ## _GRPH_INTERRUPT_STATUS,\
.ack_mask = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
.ack_value = GRPH_INTERRUPT_STATUS__GRPH_PFLIP_INT_CLEAR_MASK,\
@@ -113,7 +113,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
.enable_value = {\
CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK,\
- ~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\
+ (uint32_t)~CRTC_INTERRUPT_CONTROL__CRTC_V_UPDATE_INT_MSK_MASK},\
.ack_reg = mmCRTC ## reg_num ## _CRTC_V_UPDATE_INT_STATUS,\
.ack_mask =\
CRTC_V_UPDATE_INT_STATUS__CRTC_V_UPDATE_INT_CLEAR_MASK,\
@@ -129,7 +129,7 @@ static struct irq_source_info_funcs vupdate_irq_info_funcs = {
CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
.enable_value = {\
CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK,\
- ~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\
+ (uint32_t)~CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_INT_ENABLE_MASK},\
.ack_reg = mmCRTC ## reg_num ## _CRTC_VERTICAL_INTERRUPT0_CONTROL,\
.ack_mask =\
CRTC_VERTICAL_INTERRUPT0_CONTROL__CRTC_VERTICAL_INTERRUPT0_CLEAR_MASK,\
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c
index ca2e13702fbb..0bdb62b883aa 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn10/irq_service_dcn10.c
@@ -42,6 +42,9 @@ static enum dc_irq_source to_dal_irq_source_dcn10(struct irq_service *irq_servic
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -176,7 +179,7 @@ static struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c
index 1c4c51abc259..8a0f4b5d6956 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn20/irq_service_dcn20.c
@@ -43,6 +43,9 @@ static enum dc_irq_source to_dal_irq_source_dcn20(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -179,7 +182,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
index 9e0881472e38..9d13c0cc91f0 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn21/irq_service_dcn21.c
@@ -42,6 +42,9 @@ static enum dc_irq_source to_dal_irq_source_dcn21(struct irq_service *irq_servic
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -189,7 +192,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c
index 92bcd35723ca..78338af86666 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn30/irq_service_dcn30.c
@@ -50,6 +50,9 @@ static enum dc_irq_source to_dal_irq_source_dcn30(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -196,7 +199,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c b/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c
index 16685d066c1a..2f47a9fbcd43 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn302/irq_service_dcn302.c
@@ -37,6 +37,9 @@
static enum dc_irq_source to_dal_irq_source_dcn302(struct irq_service *irq_service, uint32_t src_id, uint32_t ext_id)
{
+ (void)ext_id;
+ (void)irq_service;
+ (void)src_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -180,7 +183,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
.enable_mask = block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\
@@ -199,7 +202,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
reg1 ## __ ## mask1 ## _MASK,\
- ~reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI_DMUB(reg2),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c b/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c
index 01d83e1922d6..236a7278a8cf 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn303/irq_service_dcn303.c
@@ -38,6 +38,9 @@ static enum dc_irq_source to_dal_irq_source_dcn303(struct irq_service *irq_servi
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -123,7 +126,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
.enable_mask = block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c b/drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c
index 2114c5669e6e..213e5da31b19 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn31/irq_service_dcn31.c
@@ -40,6 +40,9 @@ static enum dc_irq_source to_dal_irq_source_dcn31(struct irq_service *irq_servic
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -184,7 +187,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
@@ -198,7 +201,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
reg1 ## __ ## mask1 ## _MASK,\
- ~reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI_DMUB(reg2),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c b/drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c
index 16f158e0fb60..8aacc229b002 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn314/irq_service_dcn314.c
@@ -42,6 +42,9 @@ static enum dc_irq_source to_dal_irq_source_dcn314(struct irq_service *irq_servi
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -186,7 +189,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
@@ -200,7 +203,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
reg1 ## __ ## mask1 ## _MASK,\
- ~reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI_DMUB(reg2),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c b/drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c
index 8ee03c006ad6..b3bddc87afed 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn315/irq_service_dcn315.c
@@ -47,6 +47,9 @@ static enum dc_irq_source to_dal_irq_source_dcn315(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -191,7 +194,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
@@ -205,7 +208,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
reg1 ## __ ## mask1 ## _MASK,\
- ~reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI_DMUB(reg2),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c b/drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c
index 07e6f7dd6b99..f407ba72acdb 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn32/irq_service_dcn32.c
@@ -41,6 +41,9 @@ static enum dc_irq_source to_dal_irq_source_dcn32(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -195,7 +198,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
@@ -209,7 +212,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = {
reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
reg1 ## __ ## mask1 ## _MASK,\
- ~reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI_DMUB(reg2),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c b/drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c
index 3d28a5007f53..2f2985075f88 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn35/irq_service_dcn35.c
@@ -39,6 +39,9 @@ static enum dc_irq_source to_dal_irq_source_dcn35(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -184,7 +187,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
REG_STRUCT[base + reg_num].enable_value[0] = \
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
REG_STRUCT[base + reg_num].enable_value[1] = \
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \
REG_STRUCT[base + reg_num].ack_reg = SRI(reg2, block, reg_num),\
REG_STRUCT[base + reg_num].ack_mask = \
block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\
@@ -198,7 +201,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
REG_STRUCT[base].enable_value[0] = \
reg1 ## __ ## mask1 ## _MASK,\
REG_STRUCT[base].enable_value[1] = \
- ~reg1 ## __ ## mask1 ## _MASK, \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK, \
REG_STRUCT[base].ack_reg = SRI_DMUB(reg2),\
REG_STRUCT[base].ack_mask = \
reg2 ## __ ## mask2 ## _MASK,\
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c b/drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c
index f716c2590876..1ed75b53e131 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn351/irq_service_dcn351.c
@@ -18,6 +18,9 @@ static enum dc_irq_source to_dal_irq_source_dcn351(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -163,7 +166,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
REG_STRUCT[base + reg_num].enable_value[0] = \
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
REG_STRUCT[base + reg_num].enable_value[1] = \
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \
REG_STRUCT[base + reg_num].ack_reg = SRI(reg2, block, reg_num),\
REG_STRUCT[base + reg_num].ack_mask = \
block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\
@@ -177,7 +180,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
REG_STRUCT[base].enable_value[0] = \
reg1 ## __ ## mask1 ## _MASK,\
REG_STRUCT[base].enable_value[1] = \
- ~reg1 ## __ ## mask1 ## _MASK, \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK, \
REG_STRUCT[base].ack_reg = SRI_DMUB(reg2),\
REG_STRUCT[base].ack_mask = \
reg2 ## __ ## mask2 ## _MASK,\
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c b/drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c
index e718004901cf..4c321c26f02f 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn36/irq_service_dcn36.c
@@ -17,6 +17,9 @@ static enum dc_irq_source to_dal_irq_source_dcn36(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -162,7 +165,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
REG_STRUCT[base + reg_num].enable_value[0] = \
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
REG_STRUCT[base + reg_num].enable_value[1] = \
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK, \
REG_STRUCT[base + reg_num].ack_reg = SRI(reg2, block, reg_num),\
REG_STRUCT[base + reg_num].ack_mask = \
block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\
@@ -176,7 +179,7 @@ static struct irq_source_info_funcs vline0_irq_info_funcs = {
REG_STRUCT[base].enable_value[0] = \
reg1 ## __ ## mask1 ## _MASK,\
REG_STRUCT[base].enable_value[1] = \
- ~reg1 ## __ ## mask1 ## _MASK, \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK, \
REG_STRUCT[base].ack_reg = SRI_DMUB(reg2),\
REG_STRUCT[base].ack_mask = \
reg2 ## __ ## mask2 ## _MASK,\
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c b/drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c
index 2cde50b2ae22..059c5c636fd9 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn401/irq_service_dcn401.c
@@ -20,6 +20,9 @@ static enum dc_irq_source to_dal_irq_source_dcn401(
uint32_t src_id,
uint32_t ext_id)
{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
return DC_IRQ_SOURCE_VBLANK1;
@@ -175,7 +178,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = {
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
- ~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI(reg2, block, reg_num),\
.ack_mask = \
@@ -189,7 +192,7 @@ static struct irq_source_info_funcs vline2_irq_info_funcs = {
reg1 ## __ ## mask1 ## _MASK,\
.enable_value = {\
reg1 ## __ ## mask1 ## _MASK,\
- ~reg1 ## __ ## mask1 ## _MASK \
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
},\
.ack_reg = SRI_DMUB(reg2),\
.ack_mask = \
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c
new file mode 100644
index 000000000000..f4d1ce9079de
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.c
@@ -0,0 +1,415 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dm_services.h"
+#include "include/logger_interface.h"
+#include "../dce110/irq_service_dce110.h"
+
+#include "ivsrcid/dcn/irqsrcs_dcn_1_0.h"
+#include "dcn/dcn_4_2_0_offset.h"
+#include "dcn/dcn_4_2_0_sh_mask.h"
+
+#include "irq_service_dcn42.h"
+
+#define DCN_BASE__INST0_SEG2 0x000034C0
+
+static enum dc_irq_source to_dal_irq_source_dcn42(
+ struct irq_service *irq_service,
+ uint32_t src_id,
+ uint32_t ext_id)
+{
+ (void)irq_service;
+ (void)src_id;
+ (void)ext_id;
+ switch (src_id) {
+ case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
+ return DC_IRQ_SOURCE_VBLANK1;
+ case DCN_1_0__SRCID__DC_D2_OTG_VSTARTUP:
+ return DC_IRQ_SOURCE_VBLANK2;
+ case DCN_1_0__SRCID__DC_D3_OTG_VSTARTUP:
+ return DC_IRQ_SOURCE_VBLANK3;
+ case DCN_1_0__SRCID__DC_D4_OTG_VSTARTUP:
+ return DC_IRQ_SOURCE_VBLANK4;
+ case DCN_1_0__SRCID__DC_D5_OTG_VSTARTUP:
+ return DC_IRQ_SOURCE_VBLANK5;
+ case DCN_1_0__SRCID__DC_D6_OTG_VSTARTUP:
+ return DC_IRQ_SOURCE_VBLANK6;
+ case DCN_1_0__SRCID__OTG1_VERTICAL_INTERRUPT0_CONTROL:
+ return DC_IRQ_SOURCE_DC1_VLINE0;
+ case DCN_1_0__SRCID__OTG2_VERTICAL_INTERRUPT0_CONTROL:
+ return DC_IRQ_SOURCE_DC2_VLINE0;
+ case DCN_1_0__SRCID__OTG3_VERTICAL_INTERRUPT0_CONTROL:
+ return DC_IRQ_SOURCE_DC3_VLINE0;
+ case DCN_1_0__SRCID__OTG4_VERTICAL_INTERRUPT0_CONTROL:
+ return DC_IRQ_SOURCE_DC4_VLINE0;
+ case DCN_1_0__SRCID__OTG5_VERTICAL_INTERRUPT0_CONTROL:
+ return DC_IRQ_SOURCE_DC5_VLINE0;
+ case DCN_1_0__SRCID__OTG6_VERTICAL_INTERRUPT0_CONTROL:
+ return DC_IRQ_SOURCE_DC6_VLINE0;
+ case DCN_1_0__SRCID__HUBP0_FLIP_INTERRUPT:
+ return DC_IRQ_SOURCE_PFLIP1;
+ case DCN_1_0__SRCID__HUBP1_FLIP_INTERRUPT:
+ return DC_IRQ_SOURCE_PFLIP2;
+ case DCN_1_0__SRCID__HUBP2_FLIP_INTERRUPT:
+ return DC_IRQ_SOURCE_PFLIP3;
+ case DCN_1_0__SRCID__HUBP3_FLIP_INTERRUPT:
+ return DC_IRQ_SOURCE_PFLIP4;
+ case DCN_1_0__SRCID__HUBP4_FLIP_INTERRUPT:
+ return DC_IRQ_SOURCE_PFLIP5;
+ case DCN_1_0__SRCID__HUBP5_FLIP_INTERRUPT:
+ return DC_IRQ_SOURCE_PFLIP6;
+ case DCN_1_0__SRCID__OTG0_IHC_V_UPDATE_NO_LOCK_INTERRUPT:
+ return DC_IRQ_SOURCE_VUPDATE1;
+ case DCN_1_0__SRCID__OTG1_IHC_V_UPDATE_NO_LOCK_INTERRUPT:
+ return DC_IRQ_SOURCE_VUPDATE2;
+ case DCN_1_0__SRCID__OTG2_IHC_V_UPDATE_NO_LOCK_INTERRUPT:
+ return DC_IRQ_SOURCE_VUPDATE3;
+ case DCN_1_0__SRCID__OTG3_IHC_V_UPDATE_NO_LOCK_INTERRUPT:
+ return DC_IRQ_SOURCE_VUPDATE4;
+ case DCN_1_0__SRCID__OTG4_IHC_V_UPDATE_NO_LOCK_INTERRUPT:
+ return DC_IRQ_SOURCE_VUPDATE5;
+ case DCN_1_0__SRCID__OTG5_IHC_V_UPDATE_NO_LOCK_INTERRUPT:
+ return DC_IRQ_SOURCE_VUPDATE6;
+ case DCN_1_0__SRCID__DMCUB_OUTBOX_LOW_PRIORITY_READY_INT:
+ return DC_IRQ_SOURCE_DMCUB_OUTBOX;
+ case DCN_1_0__SRCID__DC_HPD1_INT:
+ /* generic src_id for all HPD and HPDRX interrupts */
+ switch (ext_id) {
+ case DCN_1_0__CTXID__DC_HPD1_INT:
+ return DC_IRQ_SOURCE_HPD1;
+ case DCN_1_0__CTXID__DC_HPD2_INT:
+ return DC_IRQ_SOURCE_HPD2;
+ case DCN_1_0__CTXID__DC_HPD3_INT:
+ return DC_IRQ_SOURCE_HPD3;
+ case DCN_1_0__CTXID__DC_HPD4_INT:
+ return DC_IRQ_SOURCE_HPD4;
+ case DCN_1_0__CTXID__DC_HPD5_INT:
+ return DC_IRQ_SOURCE_HPD5;
+ case DCN_1_0__CTXID__DC_HPD6_INT:
+ return DC_IRQ_SOURCE_HPD6;
+ case DCN_1_0__CTXID__DC_HPD1_RX_INT:
+ return DC_IRQ_SOURCE_HPD1RX;
+ case DCN_1_0__CTXID__DC_HPD2_RX_INT:
+ return DC_IRQ_SOURCE_HPD2RX;
+ case DCN_1_0__CTXID__DC_HPD3_RX_INT:
+ return DC_IRQ_SOURCE_HPD3RX;
+ case DCN_1_0__CTXID__DC_HPD4_RX_INT:
+ return DC_IRQ_SOURCE_HPD4RX;
+ case DCN_1_0__CTXID__DC_HPD5_RX_INT:
+ return DC_IRQ_SOURCE_HPD5RX;
+ case DCN_1_0__CTXID__DC_HPD6_RX_INT:
+ return DC_IRQ_SOURCE_HPD6RX;
+ default:
+ return DC_IRQ_SOURCE_INVALID;
+ }
+ break;
+ default:
+ return DC_IRQ_SOURCE_INVALID;
+ }
+
+}
+
+static struct irq_source_info_funcs hpd_irq_info_funcs = {
+ .set = NULL,
+ .ack = hpd0_ack
+};
+
+static struct irq_source_info_funcs hpd_rx_irq_info_funcs = {
+ .set = NULL,
+ .ack = NULL
+};
+
+static struct irq_source_info_funcs pflip_irq_info_funcs = {
+ .set = NULL,
+ .ack = NULL
+};
+
+static struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = {
+ .set = NULL,
+ .ack = NULL
+};
+
+static struct irq_source_info_funcs vblank_irq_info_funcs = {
+ .set = NULL,
+ .ack = NULL
+};
+
+static struct irq_source_info_funcs outbox_irq_info_funcs = {
+ .set = NULL,
+ .ack = NULL
+};
+
+static struct irq_source_info_funcs vline0_irq_info_funcs = {
+ .set = NULL,
+ .ack = NULL
+};
+
+static struct irq_source_info_funcs vline1_irq_info_funcs = {
+ .set = NULL,
+ .ack = NULL
+};
+
+static struct irq_source_info_funcs vline2_irq_info_funcs = {
+ .set = NULL,
+ .ack = NULL
+};
+
+#undef BASE_INNER
+#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
+
+/* compile time expand base address. */
+#define BASE(seg) \
+ BASE_INNER(seg)
+
+#define SRI(reg_name, block, id)\
+ (BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
+ reg ## block ## id ## _ ## reg_name)
+
+#define SRI_DMUB(reg_name)\
+ (BASE(reg ## reg_name ## _BASE_IDX) + \
+ reg ## reg_name)
+
+#define IRQ_REG_ENTRY(block, reg_num, reg1, mask1, reg2, mask2)\
+ .enable_reg = SRI(reg1, block, reg_num),\
+ .enable_mask = \
+ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
+ .enable_value = {\
+ block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK,\
+ (uint32_t)~block ## reg_num ## _ ## reg1 ## __ ## mask1 ## _MASK \
+ },\
+ .ack_reg = SRI(reg2, block, reg_num),\
+ .ack_mask = \
+ block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK,\
+ .ack_value = \
+ block ## reg_num ## _ ## reg2 ## __ ## mask2 ## _MASK \
+
+#define IRQ_REG_ENTRY_DMUB(reg1, mask1, reg2, mask2)\
+ .enable_reg = SRI_DMUB(reg1),\
+ .enable_mask = \
+ reg1 ## __ ## mask1 ## _MASK,\
+ .enable_value = {\
+ reg1 ## __ ## mask1 ## _MASK,\
+ (uint32_t)~reg1 ## __ ## mask1 ## _MASK \
+ },\
+ .ack_reg = SRI_DMUB(reg2),\
+ .ack_mask = \
+ reg2 ## __ ## mask2 ## _MASK,\
+ .ack_value = \
+ reg2 ## __ ## mask2 ## _MASK \
+
+#define hpd_int_entry(reg_num)\
+ [DC_IRQ_SOURCE_HPD1 + reg_num] = {\
+ IRQ_REG_ENTRY(HPD, reg_num,\
+ DC_HPD_INT_CONTROL, DC_HPD_INT_EN,\
+ DC_HPD_INT_CONTROL, DC_HPD_INT_ACK),\
+ .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\
+ .funcs = &hpd_irq_info_funcs\
+ }
+
+#define hpd_rx_int_entry(reg_num)\
+ [DC_IRQ_SOURCE_HPD1RX + reg_num] = {\
+ IRQ_REG_ENTRY(HPD, reg_num,\
+ DC_HPD_INT_CONTROL, DC_HPD_RX_INT_EN,\
+ DC_HPD_INT_CONTROL, DC_HPD_RX_INT_ACK),\
+ .status_reg = SRI(DC_HPD_INT_STATUS, HPD, reg_num),\
+ .funcs = &hpd_rx_irq_info_funcs\
+ }
+#define pflip_int_entry(reg_num)\
+ [DC_IRQ_SOURCE_PFLIP1 + reg_num] = {\
+ IRQ_REG_ENTRY(HUBPREQ, reg_num,\
+ DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_INT_MASK,\
+ DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_CLEAR),\
+ .funcs = &pflip_irq_info_funcs\
+ }
+
+#define vblank_int_entry(reg_num)\
+ [DC_IRQ_SOURCE_VBLANK1 + reg_num] = {\
+ IRQ_REG_ENTRY(OTG, reg_num,\
+ OTG_GLOBAL_SYNC_STATUS, VSTARTUP_INT_EN,\
+ OTG_GLOBAL_SYNC_STATUS, VSTARTUP_EVENT_CLEAR),\
+ .funcs = &vblank_irq_info_funcs\
+ }
+
+#define vupdate_no_lock_int_entry(reg_num)\
+ [DC_IRQ_SOURCE_VUPDATE1 + reg_num] = {\
+ IRQ_REG_ENTRY(OTG, reg_num,\
+ OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_INT_EN,\
+ OTG_GLOBAL_SYNC_STATUS, VUPDATE_NO_LOCK_EVENT_CLEAR),\
+ .funcs = &vupdate_no_lock_irq_info_funcs\
+ }
+
+#define vline0_int_entry(reg_num)\
+ [DC_IRQ_SOURCE_DC1_VLINE0 + reg_num] = {\
+ IRQ_REG_ENTRY(OTG, reg_num,\
+ OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE,\
+ OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_CLEAR),\
+ .funcs = &vline0_irq_info_funcs\
+ }
+#define vline1_int_entry(reg_num)\
+ [DC_IRQ_SOURCE_DC1_VLINE1 + reg_num] = {\
+ IRQ_REG_ENTRY(OTG, reg_num,\
+ OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE,\
+ OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_CLEAR),\
+ .funcs = &vline1_irq_info_funcs\
+ }
+#define vline2_int_entry(reg_num)\
+ [DC_IRQ_SOURCE_DC1_VLINE2 + reg_num] = {\
+ IRQ_REG_ENTRY(OTG, reg_num,\
+ OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE,\
+ OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_CLEAR),\
+ .funcs = &vline2_irq_info_funcs\
+ }
+#define dmub_outbox_int_entry()\
+ [DC_IRQ_SOURCE_DMCUB_OUTBOX] = {\
+ IRQ_REG_ENTRY_DMUB(\
+ DMCUB_INTERRUPT_ENABLE, DMCUB_OUTBOX1_READY_INT_EN,\
+ DMCUB_INTERRUPT_ACK, DMCUB_OUTBOX1_READY_INT_ACK),\
+ .funcs = &outbox_irq_info_funcs\
+ }
+
+#define dummy_irq_entry() \
+ {\
+ .funcs = &dummy_irq_info_funcs\
+ }
+
+#define i2c_int_entry(reg_num) \
+ [DC_IRQ_SOURCE_I2C_DDC ## reg_num] = dummy_irq_entry()
+
+#define dp_sink_int_entry(reg_num) \
+ [DC_IRQ_SOURCE_DPSINK ## reg_num] = dummy_irq_entry()
+
+#define gpio_pad_int_entry(reg_num) \
+ [DC_IRQ_SOURCE_GPIOPAD ## reg_num] = dummy_irq_entry()
+
+#define dc_underflow_int_entry(reg_num) \
+ [DC_IRQ_SOURCE_DC ## reg_num ## UNDERFLOW] = dummy_irq_entry()
+
+static struct irq_source_info_funcs dummy_irq_info_funcs = {
+ .set = dal_irq_service_dummy_set,
+ .ack = dal_irq_service_dummy_ack
+};
+
+static const struct irq_source_info irq_source_info_dcn42[DAL_IRQ_SOURCES_NUMBER] = {
+ [DC_IRQ_SOURCE_INVALID] = dummy_irq_entry(),
+ /* HPD (1-4) */
+ hpd_int_entry(0),
+ hpd_int_entry(1),
+ hpd_int_entry(2),
+ hpd_int_entry(3),
+ /* HPD RX (1-4) */
+ hpd_rx_int_entry(0),
+ hpd_rx_int_entry(1),
+ hpd_rx_int_entry(2),
+ hpd_rx_int_entry(3),
+ /* I2C (1-6) */
+ i2c_int_entry(1),
+ i2c_int_entry(2),
+ i2c_int_entry(3),
+ i2c_int_entry(4),
+ i2c_int_entry(5),
+ i2c_int_entry(6),
+ /* DP sink (1-6) keep table shape */
+ dp_sink_int_entry(1),
+ dp_sink_int_entry(2),
+ dp_sink_int_entry(3),
+ dp_sink_int_entry(4),
+ dp_sink_int_entry(5),
+ dp_sink_int_entry(6),
+ [DC_IRQ_SOURCE_TIMER] = dummy_irq_entry(),
+ /* PFLIP (1-4) */
+ pflip_int_entry(0),
+ pflip_int_entry(1),
+ pflip_int_entry(2),
+ pflip_int_entry(3),
+ [DC_IRQ_SOURCE_PFLIP5] = dummy_irq_entry(),
+ [DC_IRQ_SOURCE_PFLIP6] = dummy_irq_entry(),
+ [DC_IRQ_SOURCE_PFLIP_UNDERLAY0] = dummy_irq_entry(),
+ /* GPIO pads */
+ gpio_pad_int_entry(0),
+ gpio_pad_int_entry(1),
+ gpio_pad_int_entry(2),
+ gpio_pad_int_entry(3),
+ gpio_pad_int_entry(4),
+ gpio_pad_int_entry(5),
+ gpio_pad_int_entry(6),
+ gpio_pad_int_entry(7),
+ gpio_pad_int_entry(8),
+ gpio_pad_int_entry(9),
+ gpio_pad_int_entry(10),
+ gpio_pad_int_entry(11),
+ gpio_pad_int_entry(12),
+ gpio_pad_int_entry(13),
+ gpio_pad_int_entry(14),
+ gpio_pad_int_entry(15),
+ gpio_pad_int_entry(16),
+ gpio_pad_int_entry(17),
+ gpio_pad_int_entry(18),
+ gpio_pad_int_entry(19),
+ gpio_pad_int_entry(20),
+ gpio_pad_int_entry(21),
+ gpio_pad_int_entry(22),
+ gpio_pad_int_entry(23),
+ gpio_pad_int_entry(24),
+ gpio_pad_int_entry(25),
+ gpio_pad_int_entry(26),
+ gpio_pad_int_entry(27),
+ gpio_pad_int_entry(28),
+ gpio_pad_int_entry(29),
+ gpio_pad_int_entry(30),
+ /* Underflow (1-4 active, keep 5-6 dummy) */
+ dc_underflow_int_entry(1),
+ dc_underflow_int_entry(2),
+ dc_underflow_int_entry(3),
+ dc_underflow_int_entry(4),
+ dc_underflow_int_entry(5),
+ dc_underflow_int_entry(6),
+ [DC_IRQ_SOURCE_DMCU_SCP] = dummy_irq_entry(),
+ [DC_IRQ_SOURCE_VBIOS_SW] = dummy_irq_entry(),
+ vblank_int_entry(0),
+ vblank_int_entry(1),
+ vblank_int_entry(2),
+ vblank_int_entry(3),
+ [DC_IRQ_SOURCE_DC5_VLINE1] = dummy_irq_entry(),
+ [DC_IRQ_SOURCE_DC6_VLINE1] = dummy_irq_entry(),
+ dmub_outbox_int_entry(),
+ vupdate_no_lock_int_entry(0),
+ vupdate_no_lock_int_entry(1),
+ vupdate_no_lock_int_entry(2),
+ vupdate_no_lock_int_entry(3),
+ vline0_int_entry(0),
+ vline0_int_entry(1),
+ vline0_int_entry(2),
+ vline0_int_entry(3),
+ vline1_int_entry(0),
+ vline1_int_entry(1),
+ vline1_int_entry(2),
+ vline1_int_entry(3),
+ vline2_int_entry(0),
+ vline2_int_entry(1),
+ vline2_int_entry(2),
+ vline2_int_entry(3),
+};
+
+static const struct irq_service_funcs irq_service_funcs_dcn42 = {
+ .to_dal_irq_source = to_dal_irq_source_dcn42
+};
+
+static void dcn42_irq_construct(struct irq_service *irq_service,
+ struct irq_service_init_data *init_data)
+{
+ dal_irq_service_construct(irq_service, init_data);
+ irq_service->info = irq_source_info_dcn42;
+ irq_service->funcs = &irq_service_funcs_dcn42;
+}
+
+struct irq_service *dal_irq_service_dcn42_create(struct irq_service_init_data *init_data)
+{
+ struct irq_service *irq_service = kzalloc(sizeof(*irq_service), GFP_KERNEL);
+
+ if (!irq_service)
+ return NULL;
+
+ dcn42_irq_construct(irq_service, init_data);
+ return irq_service;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.h b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.h
new file mode 100644
index 000000000000..a3f70bce3a61
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn42/irq_service_dcn42.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2025 Advanced Micro Devices, Inc.
+ *
+ * DCN4.2 IRQ service interface (dal-dev only)
+ */
+#ifndef __IRQ_SERVICE_DCN42_H__
+#define __IRQ_SERVICE_DCN42_H__
+
+#include "../dce110/irq_service_dce110.h"
+
+struct irq_service *dal_irq_service_dcn42_create(
+ struct irq_service_init_data *init_data);
+
+#endif /* __IRQ_SERVICE_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
index 693d852b1c40..060460abc377 100644
--- a/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
+++ b/drivers/gpu/drm/amd/display/dc/link/accessories/link_dp_cts.c
@@ -66,6 +66,7 @@ static void dp_retrain_link_dp_test(struct dc_link *link,
struct dc_link_settings *link_setting,
bool skip_video_pattern)
{
+ (void)skip_video_pattern;
struct pipe_ctx *pipes[MAX_PIPES];
struct dc_state *state = link->dc->current_state;
struct dc_stream_update stream_update = { 0 };
@@ -483,6 +484,7 @@ static void set_crtc_test_pattern(struct dc_link *link,
enum dp_test_pattern test_pattern,
enum dp_test_pattern_color_space test_pattern_color_space)
{
+ (void)test_pattern_color_space;
enum controller_dp_test_pattern controller_test_pattern;
enum dc_color_depth color_depth = pipe_ctx->
stream->timing.display_color_depth;
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c
index 81bf3c5e1fdf..2a87b23582f3 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_dpia.c
@@ -81,6 +81,10 @@ static void set_dio_dpia_lane_settings(struct dc_link *link,
const struct dc_link_settings *link_settings,
const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
{
+ (void)link;
+ (void)link_res;
+ (void)link_settings;
+ (void)lane_settings;
}
static void enable_dpia_link_output(struct dc_link *link,
@@ -145,13 +149,9 @@ static void disable_dpia_link_output(struct dc_link *link,
}
static const struct link_hwss dpia_link_hwss = {
- .setup_stream_encoder = setup_dio_stream_encoder,
- .reset_stream_encoder = reset_dio_stream_encoder,
- .setup_stream_attribute = setup_dio_stream_attribute,
- .disable_link_output = disable_dpia_link_output,
- .setup_audio_output = setup_dio_audio_output,
- .enable_audio_packet = enable_dio_audio_packet,
- .disable_audio_packet = disable_dio_audio_packet,
+ /* Ensure initialization order matches the declaration in link_hwss.h
+ * for strict compiler compliance and consistency across HWSS implementations
+ */
.ext = {
.set_throttled_vcp_size = set_dio_throttled_vcp_size,
.enable_dp_link_output = enable_dpia_link_output,
@@ -159,6 +159,14 @@ static const struct link_hwss dpia_link_hwss = {
.set_dp_lane_settings = set_dio_dpia_lane_settings,
.update_stream_allocation_table = update_dpia_stream_allocation_table,
},
+
+ .setup_stream_encoder = setup_dio_stream_encoder,
+ .reset_stream_encoder = reset_dio_stream_encoder,
+ .setup_stream_attribute = setup_dio_stream_attribute,
+ .disable_link_output = disable_dpia_link_output,
+ .setup_audio_output = setup_dio_audio_output,
+ .enable_audio_packet = enable_dio_audio_packet,
+ .disable_audio_packet = disable_dio_audio_packet,
};
bool can_use_dpia_link_hwss(const struct dc_link *link,
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
index cec68c5dba13..dbbedeeed298 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_dp.c
@@ -110,6 +110,8 @@ void enable_hpo_dp_link_output(struct dc_link *link,
enum clock_source_id clock_source,
const struct dc_link_settings *link_settings)
{
+ (void)signal;
+ (void)clock_source;
if (!link_res->hpo_dp_link_enc) {
DC_LOG_ERROR("%s: invalid hpo_dp_link_enc\n", __func__);
return;
@@ -160,6 +162,7 @@ static void set_hpo_dp_lane_settings(struct dc_link *link,
const struct dc_link_settings *link_settings,
const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX])
{
+ (void)link;
link_res->hpo_dp_link_enc->funcs->set_ffe(
link_res->hpo_dp_link_enc,
link_settings,
@@ -170,6 +173,7 @@ void update_hpo_dp_stream_allocation_table(struct dc_link *link,
const struct link_resource *link_res,
const struct link_mst_stream_allocation_table *table)
{
+ (void)link;
link_res->hpo_dp_link_enc->funcs->update_stream_allocation_table(
link_res->hpo_dp_link_enc,
table);
@@ -178,6 +182,7 @@ void update_hpo_dp_stream_allocation_table(struct dc_link *link,
void setup_hpo_dp_audio_output(struct pipe_ctx *pipe_ctx,
struct audio_output *audio_output, uint32_t audio_inst)
{
+ (void)audio_output;
pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup(
pipe_ctx->stream_res.hpo_dp_stream_enc,
audio_inst,
@@ -218,6 +223,7 @@ static const struct link_hwss hpo_dp_link_hwss = {
bool can_use_hpo_dp_link_hwss(const struct dc_link *link,
const struct link_resource *link_res)
{
+ (void)link;
return link_res->hpo_dp_link_enc != NULL;
}
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
index 55c5148de800..6d5b7450b205 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_hpo_fixed_vs_pe_retimer_dp.c
@@ -74,6 +74,7 @@ static void dp_hpo_fixed_vs_pe_retimer_set_tx_ffe(struct dc_link *link,
static void dp_hpo_fixed_vs_pe_retimer_program_override_test_pattern(struct dc_link *link,
struct encoder_set_dp_phy_pattern_param *tp_params)
{
+ (void)tp_params;
uint8_t clk_src = 0xC4;
uint8_t pattern = 0x4F; /* SQ128 */
diff --git a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c
index 64742c24f7e6..3aa1375cec71 100644
--- a/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c
+++ b/drivers/gpu/drm/amd/display/dc/link/hwss/link_hwss_virtual.c
@@ -27,20 +27,26 @@
void virtual_setup_stream_encoder(struct pipe_ctx *pipe_ctx)
{
+ (void)pipe_ctx;
}
void virtual_setup_stream_attribute(struct pipe_ctx *pipe_ctx)
{
+ (void)pipe_ctx;
}
void virtual_reset_stream_encoder(struct pipe_ctx *pipe_ctx)
{
+ (void)pipe_ctx;
}
static void virtual_disable_link_output(struct dc_link *link,
const struct link_resource *link_res,
enum signal_type signal)
{
+ (void)link;
+ (void)link_res;
+ (void)signal;
}
static const struct link_hwss virtual_link_hwss = {
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 b2c020071cbf..59851924bfcd 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -150,14 +150,6 @@ static enum signal_type get_basic_signal_type(struct graphics_object_id encoder,
default:
return SIGNAL_TYPE_NONE;
}
- } else if (downstream.type == OBJECT_TYPE_ENCODER) {
- switch (downstream.id) {
- case ENCODER_ID_EXTERNAL_NUTMEG:
- case ENCODER_ID_EXTERNAL_TRAVIS:
- return SIGNAL_TYPE_DISPLAY_PORT;
- default:
- return SIGNAL_TYPE_NONE;
- }
}
return SIGNAL_TYPE_NONE;
@@ -174,6 +166,10 @@ static enum signal_type link_detect_sink_signal_type(struct dc_link *link,
struct audio_support *aud_support;
struct graphics_object_id enc_id;
+ /* External DP bridges should use DP signal regardless of connector type. */
+ if (link->ext_enc_id.id)
+ return SIGNAL_TYPE_DISPLAY_PORT;
+
if (link->is_dig_mapping_flexible)
enc_id = (struct graphics_object_id){.id = ENCODER_ID_UNKNOWN};
else
@@ -356,7 +352,7 @@ static void query_dp_dual_mode_adaptor(
*dongle = DISPLAY_DONGLE_DP_DVI_DONGLE;
sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK;
- CONN_DATA_DETECT(ddc->link, type2_dongle_buf, sizeof(type2_dongle_buf),
+ CONN_DATA_DETECT(link, type2_dongle_buf, sizeof(type2_dongle_buf),
"DP-DVI passive dongle %dMhz: ",
DP_ADAPTOR_DVI_MAX_TMDS_CLK / 1000);
return;
@@ -620,6 +616,14 @@ static bool detect_dp(struct dc_link *link,
link->dpcd_caps.usb4_dp_tun_info.dp_tun_cap.raw = 0;
}
+ if (link->ext_enc_id.id) {
+ /* Fix number of connected sinks reported by external DP bridge */
+ link->dpcd_caps.sink_count.bits.SINK_COUNT = 1;
+ /* NUTMEG requires that we use HBR, doesn't work with RBR. */
+ if (link->dpcd_caps.branch_dev_id == DP_BRANCH_DEVICE_ID_00001A)
+ link->preferred_link_setting.link_rate = LINK_RATE_HIGH;
+ }
+
return true;
}
@@ -653,8 +657,6 @@ static bool wait_for_entering_dp_alt_mode(struct dc_link *link)
unsigned long long time_taken_in_ns;
int tries_taken;
- DC_LOGGER_INIT(link->ctx->logger);
-
/**
* this function will only exist if we are on dcn21 (is_in_alt_mode is a
* function pointer, so checking to see if it is equal to 0 is the same
@@ -725,8 +727,6 @@ static void revert_dpia_mst_dsc_always_on_wa(struct dc_link *link)
static bool discover_dp_mst_topology(struct dc_link *link, enum dc_detect_reason reason)
{
- DC_LOGGER_INIT(link->ctx->logger);
-
LINK_INFO("link=%d, mst branch is now Connected\n",
link->link_index);
@@ -746,8 +746,6 @@ static bool discover_dp_mst_topology(struct dc_link *link, enum dc_detect_reason
bool link_reset_cur_dp_mst_topology(struct dc_link *link)
{
- DC_LOGGER_INIT(link->ctx->logger);
-
LINK_INFO("link=%d, mst branch is now Disconnected\n",
link->link_index);
@@ -786,6 +784,7 @@ static void verify_link_capability_destructive(struct dc_link *link,
struct dc_sink *sink,
enum dc_detect_reason reason)
{
+ (void)sink;
bool should_prepare_phy_clocks =
should_prepare_phy_clocks_for_link_verification(link->dc, reason);
@@ -824,6 +823,7 @@ static void verify_link_capability_non_destructive(struct dc_link *link)
static bool should_verify_link_capability_destructively(struct dc_link *link,
enum dc_detect_reason reason)
{
+ (void)reason;
bool destrictive = false;
struct dc_link_settings max_link_cap;
bool is_link_enc_unavailable = false;
@@ -903,11 +903,21 @@ static bool link_detect_evaluate_edid_header(uint8_t edid_header[8])
*/
static bool link_detect_ddc_probe(struct dc_link *link)
{
+ enum signal_type signal = link_detect_sink_signal_type(link, DETECT_REASON_HPD);
+ enum ddc_transaction_type transaction_type = get_ddc_transaction_type(signal);
+ uint8_t edid_header[8] = {0};
+ uint8_t zero = 0;
+ bool ddc_probed;
+
if (!link->ddc)
return false;
- uint8_t edid_header[8] = {0};
- bool ddc_probed = i2c_read(link->ddc, 0x50, edid_header, sizeof(edid_header));
+ if (link->dc->hwss.prepare_ddc)
+ link->dc->hwss.prepare_ddc(link);
+
+ set_ddc_transaction_type(link->ddc, transaction_type);
+
+ ddc_probed = link_query_ddc_data(link->ddc, 0x50, &zero, 1, edid_header, sizeof(edid_header));
if (!ddc_probed)
return false;
@@ -932,28 +942,10 @@ static bool link_detect_ddc_probe(struct dc_link *link)
*/
static bool link_detect_dac_load_detect(struct dc_link *link)
{
- struct dc_bios *bios = link->ctx->dc_bios;
- struct link_encoder *link_enc = link->link_enc;
- enum engine_id engine_id = link_enc->preferred_engine;
- enum dal_device_type device_type = DEVICE_TYPE_CRT;
- enum bp_result bp_result = BP_RESULT_UNSUPPORTED;
- uint32_t enum_id;
-
- switch (engine_id) {
- case ENGINE_ID_DACB:
- enum_id = 2;
- break;
- case ENGINE_ID_DACA:
- default:
- engine_id = ENGINE_ID_DACA;
- enum_id = 1;
- break;
- }
-
- if (bios->funcs->dac_load_detection)
- bp_result = bios->funcs->dac_load_detection(bios, engine_id, device_type, enum_id);
+ if (!link->dc->hwss.dac_load_detect)
+ return false;
- return bp_result == BP_RESULT_OK;
+ return link->dc->hwss.dac_load_detect(link);
}
/*
@@ -981,8 +973,6 @@ static bool detect_link_and_local_sink(struct dc_link *link,
enum dc_connection_type new_connection_type = dc_connection_none;
const uint32_t post_oui_delay = 30; // 30ms
- DC_LOGGER_INIT(link->ctx->logger);
-
if (dc_is_virtual_signal(link->connector_signal))
return false;
@@ -1463,8 +1453,6 @@ bool link_detect(struct dc_link *link, enum dc_detect_reason reason)
bool is_delegated_to_mst_top_mgr = false;
enum dc_connection_type pre_link_type = link->type;
- DC_LOGGER_INIT(link->ctx->logger);
-
is_local_sink_detect_success = detect_link_and_local_sink(link, reason);
if (is_local_sink_detect_success && link->local_sink)
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index 9b1d34c3438b..b4f46408a000 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -223,16 +223,32 @@ void link_get_master_pipes_with_dpms_on(const struct dc_link *link,
}
}
-static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx,
- enum engine_id eng_id,
- struct ext_hdmi_settings *settings)
+static struct ext_hdmi_settings create_ext_hdmi_settings(
+ uint8_t address,
+ uint8_t reg_num,
+ uint8_t reg_num_6g,
+ const struct i2c_reg_info *reg_settings,
+ const struct i2c_reg_info *reg_settings_6g
+)
{
- bool result = false;
- int i = 0;
- struct integrated_info *integrated_info =
- pipe_ctx->stream->ctx->dc_bios->integrated_info;
+ struct ext_hdmi_settings result = {
+ .slv_addr = address,
+ .reg_num = reg_num,
+ .reg_num_6g = reg_num_6g,
+ };
+
+ memcpy(result.reg_settings, reg_settings, sizeof(result.reg_settings));
+ memcpy(result.reg_settings_6g, reg_settings_6g, sizeof(result.reg_settings_6g));
+ return result;
+}
- if (integrated_info == NULL)
+static bool get_ext_hdmi_settings(
+ const struct integrated_info *info,
+ enum engine_id eng_id,
+ struct ext_hdmi_settings *settings
+)
+{
+ if (!settings || !info)
return false;
/*
@@ -242,422 +258,268 @@ static bool get_ext_hdmi_settings(struct pipe_ctx *pipe_ctx,
*/
// Check if current bios contains ext Hdmi settings
- if (integrated_info->gpu_cap_info & 0x20) {
- switch (eng_id) {
- case ENGINE_ID_DIGA:
- settings->slv_addr = integrated_info->dp0_ext_hdmi_slv_addr;
- settings->reg_num = integrated_info->dp0_ext_hdmi_6g_reg_num;
- settings->reg_num_6g = integrated_info->dp0_ext_hdmi_6g_reg_num;
- memmove(settings->reg_settings,
- integrated_info->dp0_ext_hdmi_reg_settings,
- sizeof(integrated_info->dp0_ext_hdmi_reg_settings));
- memmove(settings->reg_settings_6g,
- integrated_info->dp0_ext_hdmi_6g_reg_settings,
- sizeof(integrated_info->dp0_ext_hdmi_6g_reg_settings));
- result = true;
- break;
- case ENGINE_ID_DIGB:
- settings->slv_addr = integrated_info->dp1_ext_hdmi_slv_addr;
- settings->reg_num = integrated_info->dp1_ext_hdmi_6g_reg_num;
- settings->reg_num_6g = integrated_info->dp1_ext_hdmi_6g_reg_num;
- memmove(settings->reg_settings,
- integrated_info->dp1_ext_hdmi_reg_settings,
- sizeof(integrated_info->dp1_ext_hdmi_reg_settings));
- memmove(settings->reg_settings_6g,
- integrated_info->dp1_ext_hdmi_6g_reg_settings,
- sizeof(integrated_info->dp1_ext_hdmi_6g_reg_settings));
- result = true;
- break;
- case ENGINE_ID_DIGC:
- settings->slv_addr = integrated_info->dp2_ext_hdmi_slv_addr;
- settings->reg_num = integrated_info->dp2_ext_hdmi_6g_reg_num;
- settings->reg_num_6g = integrated_info->dp2_ext_hdmi_6g_reg_num;
- memmove(settings->reg_settings,
- integrated_info->dp2_ext_hdmi_reg_settings,
- sizeof(integrated_info->dp2_ext_hdmi_reg_settings));
- memmove(settings->reg_settings_6g,
- integrated_info->dp2_ext_hdmi_6g_reg_settings,
- sizeof(integrated_info->dp2_ext_hdmi_6g_reg_settings));
- result = true;
- break;
- case ENGINE_ID_DIGD:
- settings->slv_addr = integrated_info->dp3_ext_hdmi_slv_addr;
- settings->reg_num = integrated_info->dp3_ext_hdmi_6g_reg_num;
- settings->reg_num_6g = integrated_info->dp3_ext_hdmi_6g_reg_num;
- memmove(settings->reg_settings,
- integrated_info->dp3_ext_hdmi_reg_settings,
- sizeof(integrated_info->dp3_ext_hdmi_reg_settings));
- memmove(settings->reg_settings_6g,
- integrated_info->dp3_ext_hdmi_6g_reg_settings,
- sizeof(integrated_info->dp3_ext_hdmi_6g_reg_settings));
- result = true;
- break;
- default:
- break;
- }
+ if (!(info->gpu_cap_info & 0x20))
+ return false;
- if (result == true) {
- // Validate settings from bios integrated info table
- if (settings->slv_addr == 0)
- return false;
- if (settings->reg_num > 9)
- return false;
- if (settings->reg_num_6g > 3)
- return false;
+ switch (eng_id) {
+ case ENGINE_ID_DIGA:
+ *settings = create_ext_hdmi_settings(
+ info->dp0_ext_hdmi_slv_addr,
+ info->dp0_ext_hdmi_reg_num,
+ info->dp0_ext_hdmi_6g_reg_num,
+ info->dp0_ext_hdmi_reg_settings,
+ info->dp0_ext_hdmi_6g_reg_settings
+ );
+ break;
+ case ENGINE_ID_DIGB:
+ *settings = create_ext_hdmi_settings(
+ info->dp1_ext_hdmi_slv_addr,
+ info->dp1_ext_hdmi_reg_num,
+ info->dp1_ext_hdmi_6g_reg_num,
+ info->dp1_ext_hdmi_reg_settings,
+ info->dp1_ext_hdmi_6g_reg_settings
+ );
+ break;
+ case ENGINE_ID_DIGC:
+ *settings = create_ext_hdmi_settings(
+ info->dp2_ext_hdmi_slv_addr,
+ info->dp2_ext_hdmi_reg_num,
+ info->dp2_ext_hdmi_6g_reg_num,
+ info->dp2_ext_hdmi_reg_settings,
+ info->dp2_ext_hdmi_6g_reg_settings
+ );
+ break;
+ case ENGINE_ID_DIGD:
+ *settings = create_ext_hdmi_settings(
+ info->dp3_ext_hdmi_slv_addr,
+ info->dp3_ext_hdmi_reg_num,
+ info->dp3_ext_hdmi_6g_reg_num,
+ info->dp3_ext_hdmi_reg_settings,
+ info->dp3_ext_hdmi_6g_reg_settings
+ );
+ break;
+ default:
+ return false;
+ }
- for (i = 0; i < settings->reg_num; i++) {
- if (settings->reg_settings[i].i2c_reg_index > 0x20)
- return false;
- }
+ // Validate settings from bios integrated info table
+ if (
+ !settings->slv_addr
+ || settings->reg_num > ARRAY_SIZE(settings->reg_settings)
+ || settings->reg_num_6g > ARRAY_SIZE(settings->reg_settings_6g)
+ ) {
+ return false;
+ }
- for (i = 0; i < settings->reg_num_6g; i++) {
- if (settings->reg_settings_6g[i].i2c_reg_index > 0x20)
- return false;
- }
- }
+ for (size_t i = 0; i < settings->reg_num; i++) {
+ if (settings->reg_settings[i].i2c_reg_index > 0x20)
+ return false;
}
- return result;
+ for (size_t i = 0; i < settings->reg_num_6g; i++) {
+ if (settings->reg_settings_6g[i].i2c_reg_index > 0x20)
+ return false;
+ }
+ return true;
}
-static bool write_i2c(struct pipe_ctx *pipe_ctx,
- uint8_t address, uint8_t *buffer, uint32_t length)
+static bool write_i2c(
+ const struct dc_link *link,
+ uint8_t address,
+ uint8_t *buffer,
+ uint32_t length
+)
{
- struct i2c_command cmd = {0};
- struct i2c_payload payload = {0};
+ struct i2c_payload payload = {
+ .write = true,
+ .address = address,
+ .length = length,
+ .data = buffer,
+ };
+ struct i2c_command cmd = {
+ .payloads = &payload,
+ .number_of_payloads = 1,
+ .engine = I2C_COMMAND_ENGINE_DEFAULT,
+ .speed = link->ctx->dc->caps.i2c_speed_in_khz,
+ };
+
+ return dm_helpers_submit_i2c(link->ctx, link, &cmd);
+}
- memset(&payload, 0, sizeof(payload));
- memset(&cmd, 0, sizeof(cmd));
+static bool write_i2c_retimer_offset_value(
+ const struct dc_link *link,
+ uint8_t address,
+ uint8_t offset,
+ uint8_t value
+)
+{
+ DC_LOGGER_INIT(link->ctx->logger);
+ uint8_t buffer[] = { offset, value };
+ const bool success = write_i2c(link, address, buffer, sizeof(buffer));
+
+ RETIMER_REDRIVER_INFO(
+ "Retimer write, address: 0x%x, offset: 0x%x, value: 0x%x, success: %d\n",
+ address, offset, value, success
+ );
+ return success;
+}
- cmd.number_of_payloads = 1;
- cmd.engine = I2C_COMMAND_ENGINE_DEFAULT;
- cmd.speed = pipe_ctx->stream->ctx->dc->caps.i2c_speed_in_khz;
+static bool write_i2c_retimer_vga(
+ const struct dc_link *link,
+ uint8_t address
+)
+{
+ DC_LOGGER_INIT(link->ctx->logger);
+ const uint8_t vga_data[][2] = {
+ { 0xFF, 0x01 },
+ { 0x00, 0x23 },
+ { 0xFF, 0x00 },
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(vga_data); i++) {
+ if (!write_i2c_retimer_offset_value(link, address, vga_data[i][0], vga_data[i][1])) {
+ DC_LOG_ERROR("Set retimer failed, vga index: %zu\n", i);
+ return false;
+ }
+ }
+ return true;
+}
- payload.address = address;
- payload.data = buffer;
- payload.length = length;
- payload.write = true;
- cmd.payloads = &payload;
+static bool write_i2c_retimer_byte(
+ const struct dc_link *link,
+ uint8_t address,
+ uint8_t index,
+ uint8_t value
+)
+{
+ DC_LOGGER_INIT(link->ctx->logger);
+ const uint8_t apply_rx_tx_change = 0x4;
- if (dm_helpers_submit_i2c(pipe_ctx->stream->ctx,
- pipe_ctx->stream->link, &cmd))
+ if (index > 0x20)
return true;
- return false;
+ if (!write_i2c_retimer_offset_value(link, address, index, value)) {
+ DC_LOG_ERROR("Set retimer failed, 3g index: 0x%x, value: 0x%x\n", index, value);
+ return false;
+ }
+
+ // Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A
+ // needs to be set to 1 on every 0x0A-0x0C write.
+ if (0x0A <= index && index <= 0x0C) {
+ uint8_t offset = 0x0A;
+
+ // Query current value from offset 0x0A
+ if (index == 0x0A) {
+ // Just written correct value, so no need to read it back
+ } else {
+ if (!link_query_ddc_data(
+ link->ddc, address, &offset, 1, &value, 1
+ )) {
+ DC_LOG_ERROR("Set retimer failed, link_query_ddc_data\n");
+ return false;
+ }
+ }
+
+ value |= apply_rx_tx_change;
+ if (!write_i2c_retimer_offset_value(link, address, offset, value)) {
+ DC_LOG_ERROR("Set retimer failed, 3g offset: 0x%x, value: 0x%x\n", offset, value);
+ return false;
+ }
+ }
+ return true;
}
-static void write_i2c_retimer_setting(
- struct pipe_ctx *pipe_ctx,
+static bool write_i2c_retimer_setting(
+ const struct dc_link *link,
bool is_vga_mode,
bool is_over_340mhz,
struct ext_hdmi_settings *settings)
{
- uint8_t slave_address = (settings->slv_addr >> 1);
- uint8_t buffer[2];
- const uint8_t apply_rx_tx_change = 0x4;
- uint8_t offset = 0xA;
- uint8_t value = 0;
- int i = 0;
- bool i2c_success = false;
- DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
-
- memset(&buffer, 0, sizeof(buffer));
-
- /* Start Ext-Hdmi programming*/
-
- for (i = 0; i < settings->reg_num; i++) {
- /* Apply 3G settings */
- if (settings->reg_settings[i].i2c_reg_index <= 0x20) {
-
- buffer[0] = settings->reg_settings[i].i2c_reg_index;
- buffer[1] = settings->reg_settings[i].i2c_reg_val;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\
- offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
-
- if (!i2c_success)
- goto i2c_write_fail;
+ DC_LOGGER_INIT(link->ctx->logger);
+ const uint8_t address = settings->slv_addr >> 1;
- /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A
- * needs to be set to 1 on every 0xA-0xC write.
- */
- if (settings->reg_settings[i].i2c_reg_index == 0xA ||
- settings->reg_settings[i].i2c_reg_index == 0xB ||
- settings->reg_settings[i].i2c_reg_index == 0xC) {
-
- /* Query current value from offset 0xA */
- if (settings->reg_settings[i].i2c_reg_index == 0xA)
- value = settings->reg_settings[i].i2c_reg_val;
- else {
- i2c_success =
- link_query_ddc_data(
- pipe_ctx->stream->link->ddc,
- slave_address, &offset, 1, &value, 1);
- if (!i2c_success)
- goto i2c_write_fail;
- }
+ for (size_t i = 0; i < settings->reg_num; i++) {
+ const uint8_t index = settings->reg_settings[i].i2c_reg_index;
+ uint8_t value = settings->reg_settings[i].i2c_reg_val;
- buffer[0] = offset;
- /* Set APPLY_RX_TX_CHANGE bit to 1 */
- buffer[1] = value | apply_rx_tx_change;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\
- offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
- }
+ if (!write_i2c_retimer_byte(link, address, index, value)) {
+ DC_LOG_ERROR("Set retimer failed, index: %zu\n", i);
+ return false;
}
}
- /* Apply 3G settings */
if (is_over_340mhz) {
- for (i = 0; i < settings->reg_num_6g; i++) {
- /* Apply 3G settings */
- if (settings->reg_settings[i].i2c_reg_index <= 0x20) {
-
- buffer[0] = settings->reg_settings_6g[i].i2c_reg_index;
- buffer[1] = settings->reg_settings_6g[i].i2c_reg_val;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("above 340Mhz: retimer write to slave_address = 0x%x,\
- offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
-
- if (!i2c_success)
- goto i2c_write_fail;
-
- /* Based on DP159 specs, APPLY_RX_TX_CHANGE bit in 0x0A
- * needs to be set to 1 on every 0xA-0xC write.
- */
- if (settings->reg_settings_6g[i].i2c_reg_index == 0xA ||
- settings->reg_settings_6g[i].i2c_reg_index == 0xB ||
- settings->reg_settings_6g[i].i2c_reg_index == 0xC) {
-
- /* Query current value from offset 0xA */
- if (settings->reg_settings_6g[i].i2c_reg_index == 0xA)
- value = settings->reg_settings_6g[i].i2c_reg_val;
- else {
- i2c_success =
- link_query_ddc_data(
- pipe_ctx->stream->link->ddc,
- slave_address, &offset, 1, &value, 1);
- if (!i2c_success)
- goto i2c_write_fail;
- }
+ for (size_t i = 0; i < settings->reg_num_6g; i++) {
+ const uint8_t index = settings->reg_settings_6g[i].i2c_reg_index;
+ uint8_t value = settings->reg_settings_6g[i].i2c_reg_val;
- buffer[0] = offset;
- /* Set APPLY_RX_TX_CHANGE bit to 1 */
- buffer[1] = value | apply_rx_tx_change;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\
- offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
- }
+ if (!write_i2c_retimer_byte(link, address, index, value)) {
+ DC_LOG_ERROR("Set retimer failed, 6g index: %zu\n", i);
+ return false;
}
}
}
if (is_vga_mode) {
- /* Program additional settings if using 640x480 resolution */
-
- /* Write offset 0xFF to 0x01 */
- buffer[0] = 0xff;
- buffer[1] = 0x01;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\
- offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
-
- /* Write offset 0x00 to 0x23 */
- buffer[0] = 0x00;
- buffer[1] = 0x23;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\
- offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
-
- /* Write offset 0xff to 0x00 */
- buffer[0] = 0xff;
- buffer[1] = 0x00;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\
- offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
-
- }
-
- return;
-
-i2c_write_fail:
- DC_LOG_DEBUG("Set retimer failed");
+ return write_i2c_retimer_vga(link, address);
+ }
+ return true;
}
-static void write_i2c_default_retimer_setting(
- struct pipe_ctx *pipe_ctx,
+static bool write_i2c_default_retimer_setting(
+ const struct dc_link *link,
bool is_vga_mode,
bool is_over_340mhz)
{
- uint8_t slave_address = (0xBA >> 1);
- uint8_t buffer[2];
- bool i2c_success = false;
- DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
+ const uint8_t address = 0xBA >> 1;
- memset(&buffer, 0, sizeof(buffer));
-
- /* Program Slave Address for tuning single integrity */
- /* Write offset 0x0A to 0x13 */
- buffer[0] = 0x0A;
- buffer[1] = 0x13;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer writes default setting to slave_address = 0x%x,\
- offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
-
- /* Write offset 0x0A to 0x17 */
- buffer[0] = 0x0A;
- buffer[1] = 0x17;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
- offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
-
- /* Write offset 0x0B to 0xDA or 0xD8 */
- buffer[0] = 0x0B;
- buffer[1] = is_over_340mhz ? 0xDA : 0xD8;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
- offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
-
- /* Write offset 0x0A to 0x17 */
- buffer[0] = 0x0A;
- buffer[1] = 0x17;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
- offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
-
- /* Write offset 0x0C to 0x1D or 0x91 */
- buffer[0] = 0x0C;
- buffer[1] = is_over_340mhz ? 0x1D : 0x91;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
- offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
-
- /* Write offset 0x0A to 0x17 */
- buffer[0] = 0x0A;
- buffer[1] = 0x17;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
- offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
+ DC_LOGGER_INIT(link->ctx->logger);
+ const uint8_t data[][2] = {
+ { 0x0A, 0x13 },
+ { 0x0A, 0x17 },
+ { 0x0B, is_over_340mhz ? 0xDA : 0xD8 },
+ { 0x0A, 0x17 },
+ { 0x0C, is_over_340mhz ? 0x1D : 0x91 },
+ { 0x0A, 0x17 },
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(data); i++) {
+ if (!write_i2c_retimer_offset_value(link, address, data[i][0], data[i][1])) {
+ DC_LOG_ERROR("Set default retimer failed, index: %zu\n", i);
+ return false;
+ }
+ }
if (is_vga_mode) {
- /* Program additional settings if using 640x480 resolution */
-
- /* Write offset 0xFF to 0x01 */
- buffer[0] = 0xff;
- buffer[1] = 0x01;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
- offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
-
- /* Write offset 0x00 to 0x23 */
- buffer[0] = 0x00;
- buffer[1] = 0x23;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write to slave_addr = 0x%x,\
- offset = 0x%x, reg_val= 0x%x, i2c_success = %d\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
-
- /* Write offset 0xff to 0x00 */
- buffer[0] = 0xff;
- buffer[1] = 0x00;
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("retimer write default setting to slave_addr = 0x%x,\
- offset = 0x%x, reg_val= 0x%x, i2c_success = %d end here\n",
- slave_address, buffer[0], buffer[1], i2c_success?1:0);
- if (!i2c_success)
- goto i2c_write_fail;
- }
-
- return;
-
-i2c_write_fail:
- DC_LOG_DEBUG("Set default retimer failed");
+ return write_i2c_retimer_vga(link, address);
+ }
+ return true;
}
-static void write_i2c_redriver_setting(
- struct pipe_ctx *pipe_ctx,
+static bool write_i2c_redriver_setting(
+ const struct dc_link *link,
bool is_over_340mhz)
{
- uint8_t slave_address = (0xF0 >> 1);
- uint8_t buffer[16];
- bool i2c_success = false;
- DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger);
-
- memset(&buffer, 0, sizeof(buffer));
-
- // Program Slave Address for tuning single integrity
- buffer[3] = 0x4E;
- buffer[4] = 0x4E;
- buffer[5] = 0x4E;
- buffer[6] = is_over_340mhz ? 0x4E : 0x4A;
-
- i2c_success = write_i2c(pipe_ctx, slave_address,
- buffer, sizeof(buffer));
- RETIMER_REDRIVER_INFO("redriver write 0 to all 16 reg offset expect following:\n\
- \t slave_addr = 0x%x, offset[3] = 0x%x, offset[4] = 0x%x,\
- offset[5] = 0x%x,offset[6] is_over_340mhz = 0x%x,\
- i2c_success = %d\n",
- slave_address, buffer[3], buffer[4], buffer[5], buffer[6], i2c_success?1:0);
-
- if (!i2c_success)
- DC_LOG_DEBUG("Set redriver failed");
+ DC_LOGGER_INIT(link->ctx->logger);
+ const uint8_t address = 0xF0 >> 1;
+ uint8_t buffer[16] = {
+ [3] = 0x4E,
+ [4] = 0x4E,
+ [5] = 0x4E,
+ [6] = is_over_340mhz ? 0x4E : 0x4A,
+ };
+
+ const bool success = write_i2c(link, address, buffer, sizeof(buffer));
+
+ RETIMER_REDRIVER_INFO(
+ "Redriver write, address: 0x%x, buffer: { [3]: 0x%x, 0x%x, 0x%x, 0x%x }, success: %d\n",
+ address, buffer[3], buffer[4], buffer[5], buffer[6], success
+ );
+
+ if (!success)
+ DC_LOG_ERROR("Set redriver failed");
+ return success;
}
static void update_psp_stream_config(struct pipe_ctx *pipe_ctx, bool dpms_off)
@@ -1933,16 +1795,14 @@ static void enable_link_hdmi(struct pipe_ctx *pipe_ctx)
/* DP159, Retimer settings */
eng_id = pipe_ctx->stream_res.stream_enc->id;
- if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings)) {
- write_i2c_retimer_setting(pipe_ctx,
- is_vga_mode, is_over_340mhz, &settings);
+ if (get_ext_hdmi_settings(stream->ctx->dc_bios->integrated_info, eng_id, &settings)) {
+ write_i2c_retimer_setting(link, is_vga_mode, is_over_340mhz, &settings);
} else {
- write_i2c_default_retimer_setting(pipe_ctx,
- is_vga_mode, is_over_340mhz);
+ write_i2c_default_retimer_setting(link, is_vga_mode, is_over_340mhz);
}
} else if (masked_chip_caps == AMD_EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) {
/* PI3EQX1204, Redriver settings */
- write_i2c_redriver_setting(pipe_ctx, is_over_340mhz);
+ write_i2c_redriver_setting(link, is_over_340mhz);
}
}
@@ -2364,15 +2224,13 @@ void link_set_dpms_off(struct pipe_ctx *pipe_ctx)
false);
if (masked_chip_caps == AMD_EXT_DISPLAY_PATH_CAPS__HDMI20_TISN65DP159RSBT) {
/* DP159, Retimer settings */
- if (get_ext_hdmi_settings(pipe_ctx, eng_id, &settings))
- write_i2c_retimer_setting(pipe_ctx,
- false, false, &settings);
+ if (get_ext_hdmi_settings(stream->ctx->dc_bios->integrated_info, eng_id, &settings))
+ write_i2c_retimer_setting(link, false, false, &settings);
else
- write_i2c_default_retimer_setting(pipe_ctx,
- false, false);
+ write_i2c_default_retimer_setting(link, false, false);
} else if (masked_chip_caps == AMD_EXT_DISPLAY_PATH_CAPS__HDMI20_PI3EQX1204) {
/* PI3EQX1204, Redriver settings */
- write_i2c_redriver_setting(pipe_ctx, false);
+ write_i2c_redriver_setting(link, false);
}
}
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 21815ad01a29..7e7682d7dfc8 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_factory.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_factory.c
@@ -367,6 +367,18 @@ static enum transmitter translate_encoder_to_transmitter(
}
}
+static bool encoder_is_external_dp(
+ struct graphics_object_id encoder)
+{
+ switch (encoder.id) {
+ case ENCODER_ID_EXTERNAL_NUTMEG:
+ case ENCODER_ID_EXTERNAL_TRAVIS:
+ return true;
+ default:
+ return false;
+ }
+}
+
static void link_destruct(struct dc_link *link)
{
int i;
@@ -514,6 +526,13 @@ static bool construct_phy(struct dc_link *link,
* so that we avoid initializing DDC and HPD, etc.
*/
bp_funcs->get_src_obj(bios, link->link_id, 0, &link_encoder);
+
+ if (encoder_is_external_dp(link_encoder)) {
+ /* External DP bridge encoders: find the actual link encoder and use that. */
+ link->ext_enc_id = link_encoder;
+ bp_funcs->get_src_obj(bios, link->ext_enc_id, 0, &link_encoder);
+ }
+
transmitter_from_encoder = translate_encoder_to_transmitter(link_encoder);
link_analog_engine = find_analog_engine(link, &enc_init_data.analog_encoder);
@@ -691,6 +710,13 @@ static bool construct_phy(struct dc_link *link,
goto create_fail;
}
+ /* For external DP bridge encoders:
+ * Set the connector signal to DisplayPort so that they can work with
+ * the pre-existing code paths for DP without a lot of code churn.
+ */
+ if (link->ext_enc_id.id != ENCODER_ID_UNKNOWN)
+ link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT;
+
LINK_INFO("Connector[%d] description: signal: %s\n",
init_params->connector_index,
signal_type_to_string(link->connector_signal));
@@ -735,7 +761,8 @@ static bool construct_phy(struct dc_link *link,
link->device_tag.dev_id))
continue;
if (link->device_tag.dev_id.device_type == DEVICE_TYPE_CRT &&
- link->connector_signal != SIGNAL_TYPE_RGB)
+ link->connector_signal != SIGNAL_TYPE_RGB &&
+ link->ext_enc_id.id == ENCODER_ID_UNKNOWN)
continue;
if (link->device_tag.dev_id.device_type == DEVICE_TYPE_LCD &&
link->connector_signal == SIGNAL_TYPE_RGB)
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.c b/drivers/gpu/drm/amd/display/dc/link/link_validation.c
index acdc162de535..eb791285ed06 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_validation.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.c
@@ -391,6 +391,7 @@ static const struct dc_tunnel_settings *get_dp_tunnel_settings(const struct dc_s
*/
enum dc_status link_validate_dp_tunnel_bandwidth(const struct dc *dc, const struct dc_state *new_ctx)
{
+ (void)dc;
struct dc_validation_dpia_set dpia_link_sets[MAX_DPIA_NUM] = { 0 };
uint8_t link_count = 0;
enum dc_status result = DC_OK;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
index cdc7587cf0b6..e12bf3dd3e46 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c
@@ -743,6 +743,8 @@ static bool decide_dp_link_settings(struct dc_link *link, struct dc_link_setting
{
struct dc_link_settings initial_link_setting = {
LANE_COUNT_ONE, LINK_RATE_LOW, LINK_SPREAD_DISABLED, false, 0};
+ if (link->preferred_link_setting.link_rate != LINK_RATE_UNKNOWN)
+ initial_link_setting.link_rate = link->preferred_link_setting.link_rate;
struct dc_link_settings current_link_setting =
initial_link_setting;
uint32_t link_bw;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c
index 9b2f1a7da1d1..766b54631c79 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia.c
@@ -71,7 +71,7 @@ enum dc_status dpcd_get_tunneling_device_data(struct dc_link *link)
link->dpcd_caps.usb4_dp_tun_info.dpia_info.raw =
dpcd_dp_tun_data[DP_IN_ADAPTER_INFO - DP_TUNNELING_CAPABILITIES_SUPPORT];
link->dpcd_caps.usb4_dp_tun_info.usb4_driver_id =
- dpcd_dp_tun_data[DP_USB4_DRIVER_ID - DP_TUNNELING_CAPABILITIES_SUPPORT];
+ dpcd_dp_tun_data[DP_USB4_DRIVER_ID - DP_TUNNELING_CAPABILITIES_SUPPORT] & 0x0F;
if (link->dpcd_caps.usb4_dp_tun_info.dp_tun_cap.bits.dpia_bw_alloc) {
status = core_link_read_dpcd(link, USB4_DRIVER_BW_CAPABILITY,
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
index cc18a3bebef2..1860d44f63c1 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_irq_handler.c
@@ -223,9 +223,10 @@ static void handle_hpd_irq_vesa_replay_sink(struct dc_link *link)
}
}
-static void handle_hpd_irq_replay_sink(struct dc_link *link)
+static void handle_hpd_irq_replay_sink(struct dc_link *link, bool *need_re_enable)
{
union dpcd_replay_configuration replay_configuration = {0};
+ union dpcd_replay_configuration replay_sink_status = {0};
/*AMD Replay version reuse DP_PSR_ERROR_STATUS for REPLAY_ERROR status.*/
union psr_error_status replay_error_status = {0};
bool ret = false;
@@ -265,9 +266,17 @@ static void handle_hpd_irq_replay_sink(struct dc_link *link)
&replay_error_status.raw,
sizeof(replay_error_status.raw));
+ dm_helpers_dp_read_dpcd(
+ link->ctx,
+ link,
+ DP_PR_REPLAY_SINK_STATUS,
+ &replay_sink_status.raw,
+ 1);
+
if (replay_error_status.bits.LINK_CRC_ERROR ||
replay_configuration.bits.DESYNC_ERROR_STATUS ||
- replay_configuration.bits.STATE_TRANSITION_ERROR_STATUS) {
+ replay_configuration.bits.STATE_TRANSITION_ERROR_STATUS ||
+ replay_sink_status.bits.SINK_DEVICE_REPLAY_STATUS == 0x7) {
bool allow_active;
link->replay_settings.config.replay_error_status.raw |= replay_error_status.raw;
@@ -299,8 +308,7 @@ static void handle_hpd_irq_replay_sink(struct dc_link *link)
if (link->replay_settings.replay_allow_active) {
allow_active = false;
edp_set_replay_allow_active(link, &allow_active, true, false, NULL);
- allow_active = true;
- edp_set_replay_allow_active(link, &allow_active, true, false, NULL);
+ *need_re_enable = true;
}
}
}
@@ -460,6 +468,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
union device_service_irq device_service_clear = {0};
enum dc_status result;
bool status = false;
+ bool replay_re_enable_needed = false;
if (out_link_loss)
*out_link_loss = false;
@@ -519,7 +528,7 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
/* PSR-related error was detected and handled */
return true;
- handle_hpd_irq_replay_sink(link);
+ handle_hpd_irq_replay_sink(link, &replay_re_enable_needed);
/* If PSR-related error handled, Main link may be off,
* so do not handle as a normal sink status change interrupt.
@@ -538,16 +547,16 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
return false;
}
- /* For now we only handle 'Downstream port status' case.
+ /* Handle 'Downstream port status' case for all DP link types.
* If we got sink count changed it means
* Downstream port status changed,
* then DM should call DC to do the detection.
- * NOTE: Do not handle link loss on eDP since it is internal link
+ * NOTE: Now includes eDP link loss detection and retraining
*/
- if ((link->connector_signal != SIGNAL_TYPE_EDP) &&
- dp_parse_link_loss_status(
- link,
- &hpd_irq_dpcd_data)) {
+
+ if (dp_parse_link_loss_status(
+ link,
+ &hpd_irq_dpcd_data)) {
/* Connectivity log: link loss */
CONN_DATA_LINK_LOSS(link,
hpd_irq_dpcd_data.raw,
@@ -576,6 +585,11 @@ bool dp_handle_hpd_rx_irq(struct dc_link *link,
!= link->dpcd_sink_count)
status = true;
+ if (replay_re_enable_needed) {
+ bool allow_active = true;
+
+ edp_set_replay_allow_active(link, &allow_active, true, false, NULL);
+ }
/* reasons for HPD RX:
* 1. Link Loss - ie Re-train the Link
* 2. MST sideband message
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c
index 7e45d1e767bb..96afce4ffbfa 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_panel_replay.c
@@ -252,23 +252,24 @@ bool dp_pr_enable(struct dc_link *link, bool enable)
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
+ if (link->replay_settings.replay_allow_active == enable)
+ return true;
+
if (enable && !dc_is_embedded_signal(link->connector_signal))
dp_pr_set_static_screen_param(link);
- if (link->replay_settings.replay_allow_active != enable) {
- //for sending PR enable commands to DMUB
- memset(&cmd, 0, sizeof(cmd));
+ // for sending PR enable commands to DMUB
+ memset(&cmd, 0, sizeof(cmd));
- cmd.pr_enable.header.type = DMUB_CMD__PR;
- cmd.pr_enable.header.sub_type = DMUB_CMD__PR_ENABLE;
- cmd.pr_enable.header.payload_bytes = sizeof(struct dmub_cmd_pr_enable_data);
- cmd.pr_enable.data.panel_inst = panel_inst;
- cmd.pr_enable.data.enable = enable ? 1 : 0;
+ cmd.pr_enable.header.type = DMUB_CMD__PR;
+ cmd.pr_enable.header.sub_type = DMUB_CMD__PR_ENABLE;
+ cmd.pr_enable.header.payload_bytes = sizeof(struct dmub_cmd_pr_enable_data);
+ cmd.pr_enable.data.panel_inst = panel_inst;
+ cmd.pr_enable.data.enable = enable ? 1 : 0;
+ dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
- dc_wake_and_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
+ link->replay_settings.replay_allow_active = enable;
- link->replay_settings.replay_allow_active = enable;
- }
return true;
}
@@ -389,7 +390,7 @@ bool dp_pr_get_state(const struct dc_link *link, uint64_t *state)
const struct dc *dc = link->ctx->dc;
unsigned int panel_inst = 0;
uint32_t retry_count = 0;
- uint32_t replay_state = 0;
+ uint32_t replay_state = PR_STATE_INVALID;
if (!dp_pr_get_panel_inst(dc, link, &panel_inst))
return false;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
index 08e2b572e0ff..ddff0db4ce70 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training.c
@@ -554,6 +554,7 @@ enum link_training_result dp_check_link_loss_status(
struct dc_link *link,
const struct link_training_settings *link_training_setting)
{
+ (void)link_training_setting;
enum link_training_result status = LINK_TRAINING_SUCCESS;
union lane_status lane_status;
union lane_align_status_updated dpcd_lane_status_updated;
@@ -1387,6 +1388,7 @@ bool dp_set_hw_training_pattern(
enum dc_dp_training_pattern pattern,
uint32_t offset)
{
+ (void)offset;
enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
switch (pattern) {
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c
index 11565f187ac7..1a6bfc45927d 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_128b_132b.c
@@ -158,6 +158,7 @@ static enum link_training_result dp_perform_128b_132b_cds_done_sequence(
const struct link_resource *link_res,
struct link_training_settings *lt_settings)
{
+ (void)link_res;
/* Assumption: assume hardware has transmitted eq pattern */
enum dc_status status = DC_OK;
enum link_training_result result = LINK_TRAINING_SUCCESS;
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
index 603537ffd128..34fa76d97b83 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_training_dpia.c
@@ -172,6 +172,7 @@ static uint8_t dpia_build_set_config_data(
struct dc_link *link,
struct link_training_settings *lt_settings)
{
+ (void)link;
union dpia_set_config_data data;
data.raw = 0;
@@ -290,6 +291,7 @@ static enum link_training_result dpia_training_cr_non_transparent(
struct link_training_settings *lt_settings,
uint32_t hop)
{
+ (void)link_res;
enum link_training_result result = LINK_TRAINING_CR_FAIL_LANE0;
uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */
enum dc_status status = DC_ERROR_UNEXPECTED;
@@ -457,6 +459,7 @@ static enum link_training_result dpia_training_cr_transparent(
const struct link_resource *link_res,
struct link_training_settings *lt_settings)
{
+ (void)link_res;
enum link_training_result result = LINK_TRAINING_CR_FAIL_LANE0;
enum dc_status status;
uint32_t retries_cr = 0; /* Number of consecutive attempts with same VS or PE. */
@@ -585,6 +588,7 @@ static enum link_training_result dpia_training_eq_non_transparent(
struct link_training_settings *lt_settings,
uint32_t hop)
{
+ (void)link_res;
enum link_training_result result = LINK_TRAINING_EQ_FAIL_EQ;
uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */
uint32_t retries_eq = 0;
@@ -730,6 +734,7 @@ static enum link_training_result dpia_training_eq_transparent(
const struct link_resource *link_res,
struct link_training_settings *lt_settings)
{
+ (void)link_res;
enum link_training_result result = LINK_TRAINING_EQ_FAIL_EQ;
uint32_t retries_eq = 0;
enum dc_status status;
@@ -991,6 +996,7 @@ enum link_training_result dpia_perform_link_training(
const struct dc_link_settings *link_setting,
bool skip_video_pattern)
{
+ (void)skip_video_pattern;
enum link_training_result result;
struct link_training_settings lt_settings = {0};
uint8_t repeater_cnt = 0; /* Number of hops/repeaters in display path. */
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c
index 584b9295a12a..e4c2aa2bc364 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dpcd.c
@@ -180,6 +180,7 @@ static void dpcd_reduce_address_range(
uint8_t * const reduced_data,
const uint32_t reduced_size)
{
+ (void)extended_size;
const uint32_t offset = reduced_address - extended_address;
/*
diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
index aa02b38e183a..4a2699a374b7 100644
--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
@@ -100,11 +100,7 @@ void dp_set_panel_mode(struct dc_link *link, enum dp_panel_mode panel_mode)
enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
{
- /* We need to explicitly check that connector
- * is not DP. Some Travis_VGA get reported
- * by video bios as DP.
- */
- if (link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
+ if (link->ext_enc_id.id) {
switch (link->dpcd_caps.branch_dev_id) {
case DP_BRANCH_DEVICE_ID_0022B9:
@@ -124,7 +120,7 @@ enum dp_panel_mode dp_get_panel_mode(struct dc_link *link)
}
break;
case DP_BRANCH_DEVICE_ID_00001A:
- /* alternate scrambler reset is required for Travis
+ /* alternate scrambler reset is required for NUTMEG
* for the case when external chip does not provide
* sink device id, alternate scrambler scheme will
* be overriden later by querying Encoder feature
@@ -851,6 +847,7 @@ bool edp_setup_psr(struct dc_link *link,
case FAMILY_YELLOW_CARP:
case AMDGPU_FAMILY_GC_10_3_6:
case AMDGPU_FAMILY_GC_11_0_1:
+ case AMDGPU_FAMILY_GC_11_5_4:
if (dc->debug.disable_z10 || dc->debug.psr_skip_crtc_disable)
psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
break;
@@ -1098,8 +1095,6 @@ bool edp_send_replay_cmd(struct dc_link *link,
if (!replay)
return false;
- DC_LOGGER_INIT(link->ctx->logger);
-
if (dp_pr_get_panel_inst(dc, link, &panel_inst))
cmd_data->panel_inst = panel_inst;
else {
diff --git a/drivers/gpu/drm/amd/display/dc/mmhubbub/Makefile b/drivers/gpu/drm/amd/display/dc/mmhubbub/Makefile
index 2d4b7a85847d..afc376defa0b 100644
--- a/drivers/gpu/drm/amd/display/dc/mmhubbub/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/mmhubbub/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright 2020 Advanced Micro Devices, Inc.
+# Copyright 2020-2026 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -52,3 +52,11 @@ AMD_DAL_MMHUBBUB_DCN35 = $(addprefix $(AMDDALPATH)/dc/mmhubbub/dcn35/,$(MMHUBBUB
AMD_DISPLAY_FILES += $(AMD_DAL_MMHUBBUB_DCN35)
endif
+###############################################################################
+# DCN42
+###############################################################################
+MMHUBBUB_DCN42 = dcn42_mmhubbub.o
+
+AMD_DAL_MMHUBBUB_DCN42 = $(addprefix $(AMDDALPATH)/dc/mmhubbub/dcn42/,$(MMHUBBUB_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_MMHUBBUB_DCN42)
diff --git a/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.c b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.c
new file mode 100644
index 000000000000..4700bdc8701d
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dcn35/dcn35_mmhubbub.h"
+#include "dcn42_mmhubbub.h"
+#include "reg_helper.h"
+
+#define REG(reg) \
+ ((const struct dcn35_mmhubbub_registers *)(mcif_wb30->mcif_wb_regs)) \
+ ->reg
+
+#define CTX mcif_wb30->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+ ((const struct dcn35_mmhubbub_shift *)(mcif_wb30->mcif_wb_shift)) \
+ ->field_name, \
+ ((const struct dcn35_mmhubbub_mask *)(mcif_wb30->mcif_wb_mask)) \
+ ->field_name
+
+void dcn42_mmhubbub_set_fgcg(struct dcn30_mmhubbub *mcif_wb30, bool enabled)
+{
+ REG_UPDATE(MMHUBBUB_CLOCK_CNTL, MMHUBBUB_FGCG_REP_DIS, !enabled);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.h
new file mode 100644
index 000000000000..0dd1f0d2eb88
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/mmhubbub/dcn42/dcn42_mmhubbub.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2026 Advanced Micro Devices, Inc. */
+
+
+#ifndef __DCN42_MMHUBBUB_H
+#define __DCN42_MMHUBBUB_H
+
+#include "mcif_wb.h"
+#include "dcn32/dcn32_mmhubbub.h"
+#include "dcn35/dcn35_mmhubbub.h"
+
+void dcn42_mmhubbub_set_fgcg(struct dcn30_mmhubbub *mcif_wb30, bool enabled);
+#endif // __DCN42_MMHUBBUB_H
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/Makefile b/drivers/gpu/drm/amd/display/dc/mpc/Makefile
index 5402c3529f5e..cc23aae3728a 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/mpc/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright 2020 Advanced Micro Devices, Inc.
+# Copyright 2020-2026 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -69,4 +69,12 @@ AMD_DAL_MPC_DCN401 = $(addprefix $(AMDDALPATH)/dc/mpc/dcn401/,$(MPC_DCN401))
AMD_DISPLAY_FILES += $(AMD_DAL_MPC_DCN401)
+###############################################################################
+# DCN42
+###############################################################################
+MPC_DCN42 = dcn42_mpc.o
+
+AMD_DAL_MPC_DCN42 = $(addprefix $(AMDDALPATH)/dc/mpc/dcn42/,$(MPC_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_MPC_DCN42)
endif
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn10/dcn10_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn10/dcn10_mpc.c
index b23c64004dd5..27e653234850 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn10/dcn10_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn10/dcn10_mpc.c
@@ -118,9 +118,7 @@ void mpc1_assert_idle_mpcc(struct mpc *mpc, int id)
struct mpcc *mpc1_get_mpcc(struct mpc *mpc, int mpcc_id)
{
- struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
-
- ASSERT(mpcc_id < mpc10->num_mpcc);
+ ASSERT(mpcc_id < TO_DCN10_MPC(mpc)->num_mpcc);
return &(mpc->mpcc_array[mpcc_id]);
}
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c
index 6bfd2c1294e5..4c7bb0522a8c 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn30/dcn30_mpc.c
@@ -117,6 +117,9 @@ void mpc3_set_out_rate_control(
bool rate_2x_mode,
struct mpc_dwb_flow_control *flow_control)
{
+ (void)enable;
+ (void)rate_2x_mode;
+ (void)flow_control;
struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
/* Always disable mpc out rate and flow control.
@@ -908,6 +911,7 @@ static void mpc3_set_3dlut_mode(
bool is_lut_size17x17x17,
uint32_t rmu_idx)
{
+ (void)is_color_channel_12bits;
uint32_t lut_mode;
struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
@@ -1428,7 +1432,7 @@ uint32_t mpcc3_acquire_rmu(struct mpc *mpc, int mpcc_id, int rmu_idx)
}
//no vacant RMU units or invalid parameters acquire_post_bldn_3dlut
- return -1;
+ return (uint32_t)-1;
}
static int mpcc3_release_rmu(struct mpc *mpc, int mpcc_id)
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c
index badcef027b84..1f15ada109b6 100644
--- a/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn32/dcn32_mpc.c
@@ -884,6 +884,7 @@ void mpc32_set_3dlut_mode(
bool is_lut_size17x17x17,
uint32_t mpcc_id)
{
+ (void)is_color_channel_12bits;
uint32_t lut_mode;
struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
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 eeac13fdd6f5..e0617db2d0c1 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Advanced Micro Devices, Inc.
+ * Copyright 2023-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -47,6 +47,16 @@ void mpc401_update_3dlut_fast_load_select(struct mpc *mpc, int mpcc_id, int hubp
REG_SET(MPCC_MCM_3DLUT_FAST_LOAD_SELECT[mpcc_id], 0, MPCC_MCM_3DLUT_FL_SEL, hubp_idx);
}
+void mpc401_get_3dlut_fast_load_status(struct mpc *mpc, int mpcc_id, uint32_t *done, uint32_t *soft_underflow, uint32_t *hard_underflow)
+{
+ struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc);
+
+ REG_GET_3(MPCC_MCM_3DLUT_FAST_LOAD_STATUS[mpcc_id],
+ MPCC_MCM_3DLUT_FL_DONE, done,
+ MPCC_MCM_3DLUT_FL_SOFT_UNDERFLOW, soft_underflow,
+ MPCC_MCM_3DLUT_FL_HARD_UNDERFLOW, hard_underflow);
+}
+
void mpc401_set_movable_cm_location(struct mpc *mpc, enum mpcc_movable_cm_location location, int mpcc_id)
{
struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc);
@@ -63,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;
@@ -121,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:
@@ -164,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) {
@@ -188,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);
@@ -222,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);
@@ -269,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);
@@ -568,6 +562,44 @@ void mpc401_get_gamut_remap(struct mpc *mpc,
arr_reg_val, 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,
@@ -602,9 +634,11 @@ static const struct mpc_funcs dcn401_mpc_funcs = {
.set_bg_color = mpc1_set_bg_color,
.set_movable_cm_location = mpc401_set_movable_cm_location,
.update_3dlut_fast_load_select = mpc401_update_3dlut_fast_load_select,
+ .get_3dlut_fast_load_status = mpc401_get_3dlut_fast_load_status,
.populate_lut = mpc401_populate_lut,
.program_lut_read_write_control = mpc401_program_lut_read_write_control,
.program_lut_mode = mpc401_program_lut_mode,
+ .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 fdc42f8ab3ff..c16560c84453 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 Advanced Micro Devices, Inc.
+ * Copyright 2023-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -184,6 +184,7 @@ struct dcn401_mpc_mask {
struct dcn401_mpc_registers {
MPC_REG_VARIABLE_LIST_DCN4_01
+ uint32_t MPCC_CONTROL2[MAX_MPCC];
};
struct dcn401_mpc {
@@ -205,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,
@@ -249,6 +261,13 @@ void mpc_read_gamut_remap(struct mpc *mpc,
enum mpcc_gamut_remap_id gamut_remap_block_id,
uint32_t *mode_select);
+void mpc401_get_3dlut_fast_load_status(
+ struct mpc *mpc,
+ int mpcc_id,
+ uint32_t *done,
+ uint32_t *soft_underflow,
+ uint32_t *hard_underflow);
+
void mpc401_update_3dlut_fast_load_select(
struct mpc *mpc,
int mpcc_id,
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c
new file mode 100644
index 000000000000..507dbdbea600
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.c
@@ -0,0 +1,797 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "reg_helper.h"
+#include "dc.h"
+#include "dcn42_mpc.h"
+#include "dcn10/dcn10_cm_common.h"
+#include "basics/conversion.h"
+#include "mpc.h"
+
+#define REG(reg)\
+ mpc42->mpc_regs->reg
+
+#define CTX \
+ mpc42->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+ mpc42->mpc_shift->field_name, mpc42->mpc_mask->field_name
+
+
+void mpc42_init_mpcc(struct mpcc *mpcc, int mpcc_inst)
+{
+ mpcc->mpcc_id = mpcc_inst;
+ mpcc->dpp_id = 0xf;
+ mpcc->mpcc_bot = NULL;
+ mpcc->blnd_cfg.overlap_only = false;
+ mpcc->blnd_cfg.global_alpha = 0xfff;
+ mpcc->blnd_cfg.global_gain = 0xfff;
+ mpcc->blnd_cfg.background_color_bpc = 4;
+ mpcc->blnd_cfg.bottom_gain_mode = 0;
+ mpcc->blnd_cfg.top_gain = 0x1f000;
+ mpcc->blnd_cfg.bottom_inside_gain = 0x1f000;
+ mpcc->blnd_cfg.bottom_outside_gain = 0x1f000;
+ mpcc->sm_cfg.enable = false;
+ mpcc->shared_bottom = false;
+}
+
+void mpc42_update_blending(
+ struct mpc *mpc,
+ struct mpcc_blnd_cfg *blnd_cfg,
+ int mpcc_id)
+{
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+ struct mpcc *mpcc = mpc1_get_mpcc(mpc, mpcc_id);
+
+ REG_UPDATE_5(MPCC_CONTROL[mpcc_id],
+ MPCC_ALPHA_BLND_MODE, blnd_cfg->alpha_mode,
+ MPCC_ALPHA_MULTIPLIED_MODE, blnd_cfg->pre_multiplied_alpha,
+ MPCC_BLND_ACTIVE_OVERLAP_ONLY, blnd_cfg->overlap_only,
+ MPCC_BG_BPC, blnd_cfg->background_color_bpc,
+ MPCC_BOT_GAIN_MODE, blnd_cfg->bottom_gain_mode);
+ REG_UPDATE_2(MPCC_CONTROL2[mpcc_id],
+ MPCC_GLOBAL_ALPHA, blnd_cfg->global_alpha,
+ MPCC_GLOBAL_GAIN, blnd_cfg->global_gain);
+
+ REG_SET(MPCC_TOP_GAIN[mpcc_id], 0, MPCC_TOP_GAIN, blnd_cfg->top_gain);
+ REG_SET(MPCC_BOT_GAIN_INSIDE[mpcc_id], 0, MPCC_BOT_GAIN_INSIDE, blnd_cfg->bottom_inside_gain);
+ REG_SET(MPCC_BOT_GAIN_OUTSIDE[mpcc_id], 0, MPCC_BOT_GAIN_OUTSIDE, blnd_cfg->bottom_outside_gain);
+
+ mpcc->blnd_cfg = *blnd_cfg;
+}
+
+/* RMCM Shaper functions */
+void mpc42_power_on_rmcm_shaper_3dlut(
+ struct mpc *mpc,
+ uint32_t mpcc_id,
+ bool power_on)
+{
+ uint32_t power_status_shaper = 2;
+ uint32_t power_status_3dlut = 2;
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+ int max_retries = 10;
+
+ REG_SET(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], 0,
+ MPC_RMCM_3DLUT_MEM_PWR_DIS, power_on == true ? 0 : 1);
+ REG_SET(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], 0,
+ MPC_RMCM_SHAPER_MEM_PWR_DIS, power_on == true ? 0 : 1);
+ /* wait for memory to fully power up */
+ if (power_on && mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
+ REG_WAIT(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_SHAPER_MEM_PWR_STATE, 0, 1, max_retries);
+ REG_WAIT(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_3DLUT_MEM_PWR_STATE, 0, 1, max_retries);
+ }
+
+ /*read status is not mandatory, it is just for debugging*/
+ REG_GET(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_SHAPER_MEM_PWR_STATE, &power_status_shaper);
+ REG_GET(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_3DLUT_MEM_PWR_STATE, &power_status_3dlut);
+
+ if (power_status_shaper != 0 && power_on == true)
+ BREAK_TO_DEBUGGER();
+
+ if (power_status_3dlut != 0 && power_on == true)
+ BREAK_TO_DEBUGGER();
+}
+
+void mpc42_configure_rmcm_shaper_lut(
+ struct mpc *mpc,
+ bool is_ram_a,
+ uint32_t mpcc_id)
+{
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+ REG_UPDATE(MPC_RMCM_SHAPER_SCALE_G_B[mpcc_id],
+ MPC_RMCM_SHAPER_SCALE_B, 0x7000);
+ REG_UPDATE(MPC_RMCM_SHAPER_SCALE_G_B[mpcc_id],
+ MPC_RMCM_SHAPER_SCALE_G, 0x7000);
+ REG_UPDATE(MPC_RMCM_SHAPER_SCALE_R[mpcc_id],
+ MPC_RMCM_SHAPER_SCALE_R, 0x7000);
+ REG_UPDATE(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id],
+ MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, 7);
+ REG_UPDATE(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id],
+ MPC_RMCM_SHAPER_LUT_WRITE_SEL, is_ram_a == true ? 0:1);
+ REG_SET(MPC_RMCM_SHAPER_LUT_INDEX[mpcc_id], 0, MPC_RMCM_SHAPER_LUT_INDEX, 0);
+}
+
+void mpc42_program_rmcm_shaper_luta_settings(
+ struct mpc *mpc,
+ const struct pwl_params *params,
+ uint32_t mpcc_id)
+{
+ const struct gamma_curve *curve;
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+ REG_SET_2(MPC_RMCM_SHAPER_RAMA_START_CNTL_B[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
+ REG_SET_2(MPC_RMCM_SHAPER_RAMA_START_CNTL_G[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
+ REG_SET_2(MPC_RMCM_SHAPER_RAMA_START_CNTL_R[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, 0);
+
+ REG_SET_2(MPC_RMCM_SHAPER_RAMA_END_CNTL_B[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
+ REG_SET_2(MPC_RMCM_SHAPER_RAMA_END_CNTL_G[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y);
+ REG_SET_2(MPC_RMCM_SHAPER_RAMA_END_CNTL_R[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y);
+
+ curve = params->arr_curve_points;
+ if (curve) {
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_0_1[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_2_3[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_4_5[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_6_7[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_8_9[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_10_11[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_12_13[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_14_15[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_16_17[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_18_19[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_20_21[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_22_23[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_24_25[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_26_27[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_28_29[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_30_31[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMA_REGION_32_33[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+ }
+}
+
+
+void mpc42_program_rmcm_shaper_lutb_settings(
+ struct mpc *mpc,
+ const struct pwl_params *params,
+ uint32_t mpcc_id)
+{
+ const struct gamma_curve *curve;
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+ REG_SET_2(MPC_RMCM_SHAPER_RAMB_START_CNTL_B[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].blue.custom_float_x,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0);
+ REG_SET_2(MPC_RMCM_SHAPER_RAMB_START_CNTL_G[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].green.custom_float_x,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0);
+ REG_SET_2(MPC_RMCM_SHAPER_RAMB_START_CNTL_R[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B, params->corner_points[0].red.custom_float_x,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, 0);
+
+ REG_SET_2(MPC_RMCM_SHAPER_RAMB_END_CNTL_B[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].blue.custom_float_x,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].blue.custom_float_y);
+ REG_SET_2(MPC_RMCM_SHAPER_RAMB_END_CNTL_G[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].green.custom_float_x,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].green.custom_float_y);
+ REG_SET_2(MPC_RMCM_SHAPER_RAMB_END_CNTL_R[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B, params->corner_points[1].red.custom_float_x,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B, params->corner_points[1].red.custom_float_y);
+
+ curve = params->arr_curve_points;
+ if (curve) {
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_0_1[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_2_3[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_4_5[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_6_7[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_8_9[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_10_11[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_12_13[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_14_15[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_16_17[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_18_19[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_20_21[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_22_23[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_24_25[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_26_27[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_28_29[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_30_31[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+
+ curve += 2;
+ REG_SET_4(MPC_RMCM_SHAPER_RAMB_REGION_32_33[mpcc_id], 0,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, curve[0].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, curve[0].segments_num,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, curve[1].offset,
+ MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, curve[1].segments_num);
+ }
+}
+
+void mpc42_program_rmcm_shaper_lut(
+ struct mpc *mpc,
+ const struct pwl_result_data *rgb,
+ uint32_t num,
+ uint32_t mpcc_id)
+{
+ uint32_t i, red, green, blue;
+ uint32_t red_delta, green_delta, blue_delta;
+ uint32_t red_value, green_value, blue_value;
+
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+ for (i = 0; i < num; i++) {
+
+ red = rgb[i].red_reg;
+ green = rgb[i].green_reg;
+ blue = rgb[i].blue_reg;
+
+ red_delta = rgb[i].delta_red_reg;
+ green_delta = rgb[i].delta_green_reg;
+ blue_delta = rgb[i].delta_blue_reg;
+
+ red_value = ((red_delta & 0x3ff) << 14) | (red & 0x3fff);
+ green_value = ((green_delta & 0x3ff) << 14) | (green & 0x3fff);
+ blue_value = ((blue_delta & 0x3ff) << 14) | (blue & 0x3fff);
+
+ REG_SET(MPC_RMCM_SHAPER_LUT_DATA[mpcc_id], 0, MPC_RMCM_SHAPER_LUT_DATA, red_value);
+ REG_SET(MPC_RMCM_SHAPER_LUT_DATA[mpcc_id], 0, MPC_RMCM_SHAPER_LUT_DATA, green_value);
+ REG_SET(MPC_RMCM_SHAPER_LUT_DATA[mpcc_id], 0, MPC_RMCM_SHAPER_LUT_DATA, blue_value);
+ }
+}
+
+void mpc42_enable_3dlut_fl(struct mpc *mpc, bool enable, int mpcc_id)
+{
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+ //if enabled cho0se mpc 0, else: off (default value)
+ REG_UPDATE(MPC_RMCM_CNTL[mpcc_id], MPC_RMCM_CNTL, enable ? 0 : 0xF); //0xF is not connected
+
+ REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPC_RMCM_3DLUT_WRITE_EN_MASK, 0);
+
+ REG_UPDATE(MPC_RMCM_MEM_PWR_CTRL[mpcc_id], MPC_RMCM_3DLUT_MEM_PWR_DIS, enable ? 0 : 3);
+}
+
+void mpc42_update_3dlut_fast_load_select(struct mpc *mpc, int mpcc_id, int hubp_idx)
+{
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+ REG_SET(MPC_RMCM_3DLUT_FAST_LOAD_SELECT[mpcc_id], 0,
+ MPC_RMCM_3DLUT_FL_SEL,
+ hubp_idx);
+}
+
+void mpc42_populate_rmcm_lut(struct mpc *mpc, const union mcm_lut_params params,
+ bool lut_bank_a, int mpcc_id)
+{
+ const enum dc_lut_mode next_mode = lut_bank_a ? LUT_RAM_A : LUT_RAM_B;
+ const struct pwl_params *lut_shaper = params.pwl;
+
+ if (lut_shaper == NULL)
+ return;
+ if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc)
+ mpc42_power_on_rmcm_shaper_3dlut(mpc, mpcc_id, true);
+
+ mpc42_configure_rmcm_shaper_lut(mpc, next_mode == LUT_RAM_A, mpcc_id);
+
+ if (next_mode == LUT_RAM_A)
+ mpc42_program_rmcm_shaper_luta_settings(mpc, lut_shaper, mpcc_id);
+ else
+ mpc42_program_rmcm_shaper_lutb_settings(mpc, lut_shaper, mpcc_id);
+
+ mpc42_program_rmcm_shaper_lut(
+ mpc, lut_shaper->rgb_resulted, lut_shaper->hw_points_num, mpcc_id);
+
+ mpc42_power_on_rmcm_shaper_3dlut(mpc, mpcc_id, false);
+}
+
+void mpc42_program_rmcm_lut_read_write_control(struct mpc *mpc, const enum MCM_LUT_ID id,
+ bool lut_bank_a, bool enabled, int mpcc_id)
+{
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+ switch (id) {
+ case MCM_LUT_3DLUT:
+ REG_UPDATE(MPC_RMCM_3DLUT_MODE[mpcc_id], MPC_RMCM_3DLUT_MODE,
+ (!enabled) ? 0 :
+ (lut_bank_a) ? 1 : 2);
+
+ REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+ MPC_RMCM_3DLUT_RAM_SEL,
+ (lut_bank_a) ? 0 : 1);
+ break;
+ case MCM_LUT_SHAPER:
+ REG_UPDATE(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id],
+ MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, 7);
+
+ REG_UPDATE(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_id],
+ MPC_RMCM_SHAPER_LUT_WRITE_SEL,
+ lut_bank_a == true ? 0:1);
+
+ REG_SET(MPC_RMCM_SHAPER_LUT_INDEX[mpcc_id], 0,
+ MPC_RMCM_SHAPER_LUT_INDEX, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+void mpc42_program_lut_mode(struct mpc *mpc,
+ bool enable,
+ bool lut_bank_a,
+ int mpcc_id)
+{
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+ 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 CM_LUT_SIZE_171717:
+ default:
+ width = 0;
+ break;
+ }
+
+ return width;
+}
+
+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 width = mpc42_get_rmcm_3dlut_width(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)
+{
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+ REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_R[mpcc_id],
+ MPC_RMCM_3DLUT_OUT_OFFSET_R, bias,
+ MPC_RMCM_3DLUT_OUT_SCALE_R, scale);
+
+ REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_G[mpcc_id],
+ MPC_RMCM_3DLUT_OUT_OFFSET_G, bias,
+ MPC_RMCM_3DLUT_OUT_SCALE_G, scale);
+
+ REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_B[mpcc_id],
+ MPC_RMCM_3DLUT_OUT_OFFSET_B, bias,
+ MPC_RMCM_3DLUT_OUT_SCALE_B, scale);
+}
+
+void mpc42_program_rmcm_bit_depth(struct mpc *mpc, uint16_t bit_depth, int mpcc_id)
+{
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+ REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id], MPC_RMCM_3DLUT_WRITE_EN_MASK, 0xF);
+
+ //program bit_depth
+ REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+ MPC_RMCM_3DLUT_30BIT_EN,
+ (bit_depth == 10) ? 1 : 0);
+}
+
+void mpc42_set_fl_config(
+ struct mpc *mpc,
+ struct mpc_fl_3dlut_config *cfg,
+ int mpcc_id)
+{
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+ uint32_t width = mpc42_get_rmcm_3dlut_width(cfg->size);
+ /*
+ From: Jie Zhou
+
+ To program any of the memories content. The following sequence is used.
+ Set the MPCC_OGAM/SHAPER/3DLUT/1DLUT_PWR_DIS to 1 (Only need to set the one
+ that is being programmed) Set DISPCLK_G_PIPE<i>_GATE_DISABLE to 1 for the
+ MPCC pipe that’s being used, so the memory’s clock is ungated. Program the
+ target memory. Set the MPCC_OGAM/SHAPER/3DLUT/1DLUT_PWR_DIS back to 0.
+ Set DISPCLK_G_PIPE<i>_GATE_DISABLE back to 0
+ */
+
+ //disconnect fl from mpc
+ REG_SET(MPCC_MCM_3DLUT_FAST_LOAD_SELECT[mpcc_id], 0,
+ MPCC_MCM_3DLUT_FL_SEL, 0xF);
+
+ REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+ MPC_RMCM_3DLUT_WRITE_EN_MASK, 0xF);
+
+ //program bit_depth
+ REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+ MPC_RMCM_3DLUT_30BIT_EN, (cfg->bit_depth == 10) ? 1 : 0);
+
+ REG_UPDATE(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_id],
+ MPC_RMCM_3DLUT_RAM_SEL, (cfg->select_lut_bank_a) ? 0 : 1);
+
+ //bias and scale
+ REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_R[mpcc_id],
+ MPC_RMCM_3DLUT_OUT_OFFSET_R, cfg->bias,
+ MPC_RMCM_3DLUT_OUT_SCALE_R, cfg->scale);
+
+ REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_G[mpcc_id],
+ MPC_RMCM_3DLUT_OUT_OFFSET_G, cfg->bias,
+ MPC_RMCM_3DLUT_OUT_SCALE_G, cfg->scale);
+
+ REG_UPDATE_2(MPC_RMCM_3DLUT_OUT_OFFSET_B[mpcc_id],
+ MPC_RMCM_3DLUT_OUT_OFFSET_B, cfg->bias,
+ MPC_RMCM_3DLUT_OUT_SCALE_B, cfg->scale);
+
+ //width
+ REG_UPDATE_2(MPC_RMCM_3DLUT_MODE[mpcc_id],
+ MPC_RMCM_3DLUT_SIZE, width,
+ MPC_RMCM_3DLUT_MODE, (!cfg->enabled) ? 0 : (cfg->select_lut_bank_a) ? 1 : 2);
+
+ //connect to hubp
+ REG_SET(MPC_RMCM_3DLUT_FAST_LOAD_SELECT[mpcc_id], 0,
+ MPC_RMCM_3DLUT_FL_SEL, cfg->hubp_index);
+
+ //ENABLE
+ //if enabled pick mpc 0, else: off (0xF)
+ //in future we'll select specific MPC
+ REG_UPDATE(MPC_RMCM_CNTL[mpcc_id], MPC_RMCM_CNTL, cfg->enabled ? 0 : 0xF);
+}
+
+void mpc42_read_mpcc_state(
+ struct mpc *mpc,
+ int mpcc_inst,
+ struct mpcc_state *s)
+{
+ struct dcn42_mpc *mpc42 = TO_DCN42_MPC(mpc);
+
+ mpc1_read_mpcc_state(mpc, mpcc_inst, s);
+
+ if (mpcc_inst < 2) {
+ /* RMCM 3DLUT Status */
+ REG_GET_4(MPC_RMCM_MEM_PWR_CTRL[mpcc_inst], MPC_RMCM_3DLUT_MEM_PWR_FORCE, &s->rmcm_regs.rmcm_3dlut_mem_pwr_force,
+ MPC_RMCM_3DLUT_MEM_PWR_DIS, &s->rmcm_regs.rmcm_3dlut_mem_pwr_dis,
+ MPC_RMCM_3DLUT_MEM_LOW_PWR_MODE, &s->rmcm_regs.rmcm_3dlut_mem_pwr_mode,
+ MPC_RMCM_3DLUT_MEM_PWR_STATE, &s->rmcm_regs.rmcm_3dlut_mem_pwr_state);
+
+ REG_GET_3(MPC_RMCM_3DLUT_MODE[mpcc_inst], MPC_RMCM_3DLUT_SIZE, &s->rmcm_regs.rmcm_3dlut_size,
+ MPC_RMCM_3DLUT_MODE, &s->rmcm_regs.rmcm_3dlut_mode,
+ MPC_RMCM_3DLUT_MODE_CURRENT, &s->rmcm_regs.rmcm_3dlut_mode_cur);
+
+ REG_GET_4(MPC_RMCM_3DLUT_READ_WRITE_CONTROL[mpcc_inst], MPC_RMCM_3DLUT_READ_SEL, &s->rmcm_regs.rmcm_3dlut_read_sel,
+ MPC_RMCM_3DLUT_30BIT_EN, &s->rmcm_regs.rmcm_3dlut_30bit_en,
+ MPC_RMCM_3DLUT_WRITE_EN_MASK, &s->rmcm_regs.rmcm_3dlut_wr_en_mask,
+ MPC_RMCM_3DLUT_RAM_SEL, &s->rmcm_regs.rmcm_3dlut_ram_sel);
+
+ REG_GET(MPC_RMCM_3DLUT_OUT_NORM_FACTOR[mpcc_inst], MPC_RMCM_3DLUT_OUT_NORM_FACTOR, &s->rmcm_regs.rmcm_3dlut_out_norm_factor);
+
+ REG_GET(MPC_RMCM_3DLUT_FAST_LOAD_SELECT[mpcc_inst], MPC_RMCM_3DLUT_FL_SEL, &s->rmcm_regs.rmcm_3dlut_fl_sel);
+
+ REG_GET_2(MPC_RMCM_3DLUT_OUT_OFFSET_R[mpcc_inst], MPC_RMCM_3DLUT_OUT_OFFSET_R, &s->rmcm_regs.rmcm_3dlut_out_offset_r,
+ MPC_RMCM_3DLUT_OUT_SCALE_R, &s->rmcm_regs.rmcm_3dlut_out_scale_r);
+
+ REG_GET_3(MPC_RMCM_3DLUT_FAST_LOAD_STATUS[mpcc_inst], MPC_RMCM_3DLUT_FL_DONE, &s->rmcm_regs.rmcm_3dlut_fl_done,
+ MPC_RMCM_3DLUT_FL_SOFT_UNDERFLOW, &s->rmcm_regs.rmcm_3dlut_fl_soft_underflow,
+ MPC_RMCM_3DLUT_FL_HARD_UNDERFLOW, &s->rmcm_regs.rmcm_3dlut_fl_hard_underflow);
+
+ /* RMCM Shaper Status */
+ REG_GET_4(MPC_RMCM_MEM_PWR_CTRL[mpcc_inst], MPC_RMCM_SHAPER_MEM_PWR_FORCE, &s->rmcm_regs.rmcm_shaper_mem_pwr_force,
+ MPC_RMCM_SHAPER_MEM_PWR_DIS, &s->rmcm_regs.rmcm_shaper_mem_pwr_dis,
+ MPC_RMCM_SHAPER_MEM_LOW_PWR_MODE, &s->rmcm_regs.rmcm_shaper_mem_pwr_mode,
+ MPC_RMCM_SHAPER_MEM_PWR_STATE, &s->rmcm_regs.rmcm_shaper_mem_pwr_state);
+
+ REG_GET_2(MPC_RMCM_SHAPER_CONTROL[mpcc_inst], MPC_RMCM_SHAPER_LUT_MODE, &s->rmcm_regs.rmcm_shaper_lut_mode,
+ MPC_RMCM_SHAPER_MODE_CURRENT, &s->rmcm_regs.rmcm_shaper_mode_cur);
+
+ REG_GET_2(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[mpcc_inst], MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, &s->rmcm_regs.rmcm_shaper_lut_write_en_mask,
+ MPC_RMCM_SHAPER_LUT_WRITE_SEL, &s->rmcm_regs.rmcm_shaper_lut_write_sel);
+
+ REG_GET(MPC_RMCM_SHAPER_OFFSET_B[mpcc_inst], MPC_RMCM_SHAPER_OFFSET_B, &s->rmcm_regs.rmcm_shaper_offset_b);
+
+ REG_GET(MPC_RMCM_SHAPER_SCALE_G_B[mpcc_inst], MPC_RMCM_SHAPER_SCALE_B, &s->rmcm_regs.rmcm_shaper_scale_b);
+
+ REG_GET_2(MPC_RMCM_SHAPER_RAMA_START_CNTL_B[mpcc_inst], MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, &s->rmcm_regs.rmcm_shaper_rama_exp_region_start_b,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, &s->rmcm_regs.rmcm_shaper_rama_exp_region_start_seg_b);
+
+ REG_GET_2(MPC_RMCM_SHAPER_RAMA_END_CNTL_B[mpcc_inst], MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, &s->rmcm_regs.rmcm_shaper_rama_exp_region_end_b,
+ MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, &s->rmcm_regs.rmcm_shaper_rama_exp_region_end_base_b);
+
+ REG_GET(MPC_RMCM_CNTL[mpcc_inst], MPC_RMCM_CNTL, &s->rmcm_regs.rmcm_cntl);
+ }
+}
+
+static const struct mpc_funcs dcn42_mpc_funcs = {
+ .read_mpcc_state = mpc42_read_mpcc_state,
+ .insert_plane = mpc1_insert_plane,
+ .remove_mpcc = mpc1_remove_mpcc,
+ .mpc_init = mpc32_mpc_init,
+ .mpc_init_single_inst = mpc3_mpc_init_single_inst,
+ .update_blending = mpc42_update_blending,
+ .cursor_lock = mpc1_cursor_lock,
+ .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp,
+ .wait_for_idle = mpc2_assert_idle_mpcc,
+ .assert_mpcc_idle_before_connect = mpc2_assert_mpcc_idle_before_connect,
+ .init_mpcc_list_from_hw = mpc1_init_mpcc_list_from_hw,
+ .set_denorm = mpc3_set_denorm,
+ .set_denorm_clamp = mpc3_set_denorm_clamp,
+ .set_output_csc = mpc3_set_output_csc,
+ .set_ocsc_default = mpc3_set_ocsc_default,
+ .set_output_gamma = mpc3_set_output_gamma,
+ .set_dwb_mux = mpc3_set_dwb_mux,
+ .disable_dwb_mux = mpc3_disable_dwb_mux,
+ .is_dwb_idle = mpc3_is_dwb_idle,
+ .set_gamut_remap = mpc401_set_gamut_remap,
+ .program_shaper = mpc32_program_shaper,
+ .program_3dlut = mpc32_program_3dlut,
+ .program_1dlut = mpc32_program_post1dlut,
+ .power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut,
+ .get_mpc_out_mux = mpc1_get_mpc_out_mux,
+ .mpc_read_reg_state = mpc3_read_reg_state,
+ .set_bg_color = mpc1_set_bg_color,
+ .set_movable_cm_location = mpc401_set_movable_cm_location,
+ .update_3dlut_fast_load_select = mpc401_update_3dlut_fast_load_select,
+ .get_3dlut_fast_load_status = mpc401_get_3dlut_fast_load_status,
+ .populate_lut = mpc401_populate_lut,
+ .program_lut_read_write_control = mpc401_program_lut_read_write_control,
+ .program_lut_mode = mpc401_program_lut_mode,
+ .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,
+ .program_lut_read_write_control = mpc42_program_rmcm_lut_read_write_control,
+ .program_lut_mode = mpc42_program_lut_mode,
+ .program_3dlut_size = mpc42_program_rmcm_3dlut_size,
+ .program_bias_scale = mpc42_program_rmcm_3dlut_fast_load_bias_scale,
+ .program_bit_depth = mpc42_program_rmcm_bit_depth,
+ .power_on_shaper_3dlut = mpc42_power_on_rmcm_shaper_3dlut,
+ .populate_lut = mpc42_populate_rmcm_lut,
+ .fl_3dlut_configure = mpc42_set_fl_config,
+ },
+};
+
+void dcn42_mpc_construct(struct dcn42_mpc *mpc42,
+ struct dc_context *ctx,
+ const struct dcn42_mpc_registers *mpc_regs,
+ const struct dcn42_mpc_shift *mpc_shift,
+ const struct dcn42_mpc_mask *mpc_mask,
+ int num_mpcc,
+ int num_rmu)
+{
+ int i;
+
+ mpc42->base.ctx = ctx;
+
+ mpc42->base.funcs = &dcn42_mpc_funcs;
+
+ mpc42->mpc_regs = mpc_regs;
+ mpc42->mpc_shift = mpc_shift;
+ mpc42->mpc_mask = mpc_mask;
+
+ mpc42->mpcc_in_use_mask = 0;
+ mpc42->num_mpcc = num_mpcc;
+ mpc42->num_rmu = num_rmu;
+
+ for (i = 0; i < MAX_MPCC; i++)
+ mpc42_init_mpcc(&mpc42->base.mpcc_array[i], i);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h
new file mode 100644
index 000000000000..a5f7f4f2bb3b
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/mpc/dcn42/dcn42_mpc.h
@@ -0,0 +1,962 @@
+/* SPDX-License-Identifier: MIT */
+/* Copyright 2026 Advanced Micro Devices, Inc. */
+
+#ifndef __DC_MPCC_DCN42_H__
+#define __DC_MPCC_DCN42_H__
+
+#include "dcn401/dcn401_mpc.h"
+
+#define TO_DCN42_MPC(mpc_base) \
+ container_of(mpc_base, struct dcn42_mpc, base)
+
+#define MPC_COMMON_MASK_SH_LIST_DCN42(mask_sh) \
+ SF(MPCC0_MPCC_TOP_SEL, MPCC_TOP_SEL, mask_sh),\
+ SF(MPCC0_MPCC_BOT_SEL, MPCC_BOT_SEL, mask_sh),\
+ SF(MPCC0_MPCC_CONTROL, MPCC_MODE, mask_sh),\
+ SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_BLND_MODE, mask_sh),\
+ SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_MULTIPLIED_MODE, mask_sh),\
+ SF(MPCC0_MPCC_CONTROL, MPCC_BLND_ACTIVE_OVERLAP_ONLY, mask_sh),\
+ SF(MPCC0_MPCC_CONTROL2, MPCC_GLOBAL_ALPHA, mask_sh),\
+ SF(MPCC0_MPCC_CONTROL2, MPCC_GLOBAL_GAIN, mask_sh),\
+ SF(MPCC0_MPCC_STATUS, MPCC_IDLE, mask_sh),\
+ SF(MPCC0_MPCC_STATUS, MPCC_BUSY, mask_sh),\
+ SF(MPCC0_MPCC_OPP_ID, MPCC_OPP_ID, mask_sh),\
+ SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\
+ SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\
+ SF(MPCC0_MPCC_BG_B_CB, MPCC_BG_B_CB, mask_sh),\
+ SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_EN, mask_sh),\
+ SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_MODE, mask_sh),\
+ SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FRAME_ALT, mask_sh),\
+ SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FIELD_ALT, mask_sh),\
+ SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_FRAME_POL, mask_sh),\
+ SF(MPCC0_MPCC_SM_CONTROL, MPCC_SM_FORCE_NEXT_TOP_POL, mask_sh),\
+ SF(MPC_OUT0_MUX, MPC_OUT_MUX, mask_sh),\
+ SF(MPCC0_MPCC_UPDATE_LOCK_SEL, MPCC_UPDATE_LOCK_SEL, mask_sh),\
+ SF(MPCC0_MPCC_CONTROL, MPCC_BG_BPC, mask_sh),\
+ SF(MPCC0_MPCC_CONTROL, MPCC_BOT_GAIN_MODE, mask_sh),\
+ SF(MPCC0_MPCC_TOP_GAIN, MPCC_TOP_GAIN, mask_sh),\
+ SF(MPCC0_MPCC_BOT_GAIN_INSIDE, MPCC_BOT_GAIN_INSIDE, mask_sh),\
+ SF(MPCC0_MPCC_BOT_GAIN_OUTSIDE, MPCC_BOT_GAIN_OUTSIDE, mask_sh),\
+ SF(MPCC0_MPCC_MOVABLE_CM_LOCATION_CONTROL, MPCC_MOVABLE_CM_LOCATION_CNTL, mask_sh),\
+ SF(MPCC0_MPCC_MOVABLE_CM_LOCATION_CONTROL, MPCC_MOVABLE_CM_LOCATION_CNTL_CURRENT, mask_sh),\
+ SF(MPC_OUT0_CSC_MODE, MPC_OCSC_MODE, mask_sh),\
+ SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C11_A, mask_sh),\
+ SF(MPC_OUT0_CSC_C11_C12_A, MPC_OCSC_C12_A, mask_sh),\
+ SF(MPCC0_MPCC_STATUS, MPCC_DISABLED, mask_sh),\
+ SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_FORCE, mask_sh),\
+ SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_DIS, mask_sh),\
+ SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_LOW_PWR_MODE, mask_sh),\
+ SF(MPCC0_MPCC_MEM_PWR_CTRL, MPCC_OGAM_MEM_PWR_STATE, mask_sh),\
+ SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_MODE, mask_sh),\
+ SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MAX_R_CR, mask_sh),\
+ SF(MPC_OUT0_DENORM_CONTROL, MPC_OUT_DENORM_CLAMP_MIN_R_CR, mask_sh),\
+ SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MAX_G_Y, mask_sh),\
+ SF(MPC_OUT0_DENORM_CLAMP_G_Y, MPC_OUT_DENORM_CLAMP_MIN_G_Y, mask_sh),\
+ SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MAX_B_CB, mask_sh),\
+ SF(MPC_OUT0_DENORM_CLAMP_B_CB, MPC_OUT_DENORM_CLAMP_MIN_B_CB, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_MODE, MPCC_GAMUT_REMAP_MODE_CURRENT, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_GAMUT_REMAP_COEF_FORMAT, MPCC_GAMUT_REMAP_COEF_FORMAT, mask_sh),\
+ SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C11_A, mask_sh),\
+ SF(MPCC_OGAM0_MPC_GAMUT_REMAP_C11_C12_A, MPCC_GAMUT_REMAP_C12_A, mask_sh),\
+ SF(MPC_DWB0_MUX, MPC_DWB0_MUX, mask_sh),\
+ SF(MPC_DWB0_MUX, MPC_DWB0_MUX_STATUS, mask_sh),\
+ SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL, mask_sh),\
+ SF(MPC_OUT0_MUX, MPC_OUT_RATE_CONTROL_DISABLE, mask_sh),\
+ SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_MODE, mask_sh),\
+ SF(MPC_OUT0_MUX, MPC_OUT_FLOW_CONTROL_COUNT, mask_sh), \
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_REGION_0_1, MPCC_OGAM_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL2_B, MPCC_OGAM_RAMA_EXP_REGION_END_B, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_END_CNTL1_B, MPCC_OGAM_RAMA_EXP_REGION_END_BASE_B, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_SLOPE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_BASE_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_BASE_B, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_B, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_START_CNTL_B, MPCC_OGAM_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_B, MPCC_OGAM_RAMA_OFFSET_B, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_G, MPCC_OGAM_RAMA_OFFSET_G, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_RAMA_OFFSET_R, MPCC_OGAM_RAMA_OFFSET_R, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_LUT_INDEX, MPCC_OGAM_LUT_INDEX, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_PWL_DISABLE, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_MODE_CURRENT, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_CONTROL, MPCC_OGAM_SELECT_CURRENT, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_WRITE_COLOR_MASK, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_READ_COLOR_SEL, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_HOST_SEL, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_LUT_CONTROL, MPCC_OGAM_LUT_CONFIG_MODE, mask_sh),\
+ SF(MPCC_OGAM0_MPCC_OGAM_LUT_DATA, MPCC_OGAM_LUT_DATA, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_MODE, MPCC_MCM_3DLUT_MODE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_MODE, MPCC_MCM_3DLUT_SIZE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_MODE, MPCC_MCM_3DLUT_MODE_CURRENT, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM_3DLUT_WRITE_EN_MASK, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM_3DLUT_RAM_SEL, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM_3DLUT_30BIT_EN, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_READ_WRITE_CONTROL, MPCC_MCM_3DLUT_READ_SEL, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_INDEX, MPCC_MCM_3DLUT_INDEX, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_DATA, MPCC_MCM_3DLUT_DATA0, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_DATA, MPCC_MCM_3DLUT_DATA1, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_DATA_30BIT, MPCC_MCM_3DLUT_DATA_30BIT, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_CONTROL, MPCC_MCM_SHAPER_LUT_MODE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_CONTROL, MPCC_MCM_SHAPER_MODE_CURRENT, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_OFFSET_R, MPCC_MCM_SHAPER_OFFSET_R, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_OFFSET_G, MPCC_MCM_SHAPER_OFFSET_G, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_OFFSET_B, MPCC_MCM_SHAPER_OFFSET_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_SCALE_R, MPCC_MCM_SHAPER_SCALE_R, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_SCALE_G_B, MPCC_MCM_SHAPER_SCALE_G, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_SCALE_G_B, MPCC_MCM_SHAPER_SCALE_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_LUT_INDEX, MPCC_MCM_SHAPER_LUT_INDEX, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_LUT_DATA, MPCC_MCM_SHAPER_LUT_DATA, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_LUT_WRITE_EN_MASK, MPCC_MCM_SHAPER_LUT_WRITE_SEL, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_START_CNTL_B, MPCC_MCM_SHAPER_RAMA_EXP_REGION_START_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_START_CNTL_B, MPCC_MCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_END_CNTL_B, MPCC_MCM_SHAPER_RAMA_EXP_REGION_END_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_END_CNTL_B, MPCC_MCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_SHAPER_RAMA_REGION_0_1, MPCC_MCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_MODE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_SELECT, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_PWL_DISABLE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_MODE_CURRENT, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_CONTROL, MPCC_MCM_1DLUT_SELECT_CURRENT, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_INDEX, MPCC_MCM_1DLUT_LUT_INDEX, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_DATA, MPCC_MCM_1DLUT_LUT_DATA, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_WRITE_COLOR_MASK, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_READ_COLOR_SEL, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_HOST_SEL, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_LUT_CONTROL, MPCC_MCM_1DLUT_LUT_CONFIG_MODE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_SLOPE_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_SLOPE_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_START_BASE_CNTL_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_START_BASE_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_END_CNTL1_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_BASE_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_END_CNTL2_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_END_CNTL2_B, MPCC_MCM_1DLUT_RAMA_EXP_REGION_END_SLOPE_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_OFFSET_B, MPCC_MCM_1DLUT_RAMA_OFFSET_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM_1DLUT_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM_1DLUT_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM_1DLUT_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_1DLUT_RAMA_REGION_0_1, MPCC_MCM_1DLUT_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_SHAPER_MEM_PWR_FORCE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_SHAPER_MEM_PWR_DIS, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_SHAPER_MEM_LOW_PWR_MODE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_3DLUT_MEM_PWR_FORCE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_3DLUT_MEM_PWR_DIS, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_3DLUT_MEM_LOW_PWR_MODE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_1DLUT_MEM_PWR_FORCE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_1DLUT_MEM_PWR_DIS, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_1DLUT_MEM_LOW_PWR_MODE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_SHAPER_MEM_PWR_STATE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_3DLUT_MEM_PWR_STATE, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_MEM_PWR_CTRL, MPCC_MCM_1DLUT_MEM_PWR_STATE, mask_sh),\
+ SF(CUR_VUPDATE_LOCK_SET0, CUR_VUPDATE_LOCK_SET, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_FIRST_GAMUT_REMAP_COEF_FORMAT, MPCC_MCM_FIRST_GAMUT_REMAP_COEF_FORMAT, mask_sh), \
+ SF(MPCC_MCM0_MPCC_MCM_FIRST_GAMUT_REMAP_MODE, MPCC_MCM_FIRST_GAMUT_REMAP_MODE, mask_sh), \
+ SF(MPCC_MCM0_MPCC_MCM_FIRST_GAMUT_REMAP_MODE, MPCC_MCM_FIRST_GAMUT_REMAP_MODE_CURRENT, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C11_C12_A, MPCC_MCM_FIRST_GAMUT_REMAP_C11_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C11_C12_A, MPCC_MCM_FIRST_GAMUT_REMAP_C12_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C13_C14_A, MPCC_MCM_FIRST_GAMUT_REMAP_C13_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C13_C14_A, MPCC_MCM_FIRST_GAMUT_REMAP_C14_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C21_C22_A, MPCC_MCM_FIRST_GAMUT_REMAP_C21_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C21_C22_A, MPCC_MCM_FIRST_GAMUT_REMAP_C22_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C23_C24_A, MPCC_MCM_FIRST_GAMUT_REMAP_C23_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C23_C24_A, MPCC_MCM_FIRST_GAMUT_REMAP_C24_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C31_C32_A, MPCC_MCM_FIRST_GAMUT_REMAP_C31_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C31_C32_A, MPCC_MCM_FIRST_GAMUT_REMAP_C32_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C33_C34_A, MPCC_MCM_FIRST_GAMUT_REMAP_C33_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_FIRST_GAMUT_REMAP_C33_C34_A, MPCC_MCM_FIRST_GAMUT_REMAP_C34_A, mask_sh), \
+ SF(MPCC_MCM0_MPCC_MCM_SECOND_GAMUT_REMAP_COEF_FORMAT, MPCC_MCM_SECOND_GAMUT_REMAP_COEF_FORMAT, mask_sh), \
+ SF(MPCC_MCM0_MPCC_MCM_SECOND_GAMUT_REMAP_MODE, MPCC_MCM_SECOND_GAMUT_REMAP_MODE, mask_sh), \
+ SF(MPCC_MCM0_MPCC_MCM_SECOND_GAMUT_REMAP_MODE, MPCC_MCM_SECOND_GAMUT_REMAP_MODE_CURRENT, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C11_C12_A, MPCC_MCM_SECOND_GAMUT_REMAP_C11_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C11_C12_A, MPCC_MCM_SECOND_GAMUT_REMAP_C12_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C13_C14_A, MPCC_MCM_SECOND_GAMUT_REMAP_C13_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C13_C14_A, MPCC_MCM_SECOND_GAMUT_REMAP_C14_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C21_C22_A, MPCC_MCM_SECOND_GAMUT_REMAP_C21_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C21_C22_A, MPCC_MCM_SECOND_GAMUT_REMAP_C22_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C23_C24_A, MPCC_MCM_SECOND_GAMUT_REMAP_C23_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C23_C24_A, MPCC_MCM_SECOND_GAMUT_REMAP_C24_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C31_C32_A, MPCC_MCM_SECOND_GAMUT_REMAP_C31_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C31_C32_A, MPCC_MCM_SECOND_GAMUT_REMAP_C32_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C33_C34_A, MPCC_MCM_SECOND_GAMUT_REMAP_C33_A, mask_sh), \
+ SF(MPCC_MCM0_MPC_MCM_SECOND_GAMUT_REMAP_C33_C34_A, MPCC_MCM_SECOND_GAMUT_REMAP_C34_A, mask_sh), \
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_FAST_LOAD_SELECT, MPCC_MCM_3DLUT_FL_SEL, mask_sh), \
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_FAST_LOAD_STATUS, MPCC_MCM_3DLUT_FL_DONE, mask_sh), \
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_FAST_LOAD_STATUS, MPCC_MCM_3DLUT_FL_SOFT_UNDERFLOW, mask_sh), \
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_FAST_LOAD_STATUS, MPCC_MCM_3DLUT_FL_HARD_UNDERFLOW, mask_sh), \
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_R, MPCC_MCM_3DLUT_OUT_OFFSET_R, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_R, MPCC_MCM_3DLUT_OUT_SCALE_R, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_G, MPCC_MCM_3DLUT_OUT_OFFSET_G, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_G, MPCC_MCM_3DLUT_OUT_SCALE_G, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_B, MPCC_MCM_3DLUT_OUT_OFFSET_B, mask_sh),\
+ SF(MPCC_MCM0_MPCC_MCM_3DLUT_OUT_OFFSET_B, MPCC_MCM_3DLUT_OUT_SCALE_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_CONTROL, MPC_RMCM_SHAPER_LUT_MODE, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_CONTROL, MPC_RMCM_SHAPER_MODE_CURRENT, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_OFFSET_R, MPC_RMCM_SHAPER_OFFSET_R, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_OFFSET_G, MPC_RMCM_SHAPER_OFFSET_G, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_OFFSET_B, MPC_RMCM_SHAPER_OFFSET_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_SCALE_R, MPC_RMCM_SHAPER_SCALE_R, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_SCALE_G_B, MPC_RMCM_SHAPER_SCALE_G, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_SCALE_G_B, MPC_RMCM_SHAPER_SCALE_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_LUT_INDEX, MPC_RMCM_SHAPER_LUT_INDEX, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_LUT_DATA, MPC_RMCM_SHAPER_LUT_DATA, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, MPC_RMCM_SHAPER_LUT_WRITE_SEL, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_B, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_B, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_G, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_G, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_G, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_R, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_R, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_START_CNTL_R, MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_B, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_B, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_G, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_G, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_G, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_G, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_R, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_R, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_END_CNTL_R, MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_R, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM_SHAPER_RAMA_EXP_REGION2_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM_SHAPER_RAMA_EXP_REGION2_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM_SHAPER_RAMA_EXP_REGION3_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM_SHAPER_RAMA_EXP_REGION3_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM_SHAPER_RAMA_EXP_REGION4_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM_SHAPER_RAMA_EXP_REGION4_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM_SHAPER_RAMA_EXP_REGION5_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM_SHAPER_RAMA_EXP_REGION5_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM_SHAPER_RAMA_EXP_REGION6_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM_SHAPER_RAMA_EXP_REGION6_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM_SHAPER_RAMA_EXP_REGION7_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM_SHAPER_RAMA_EXP_REGION7_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM_SHAPER_RAMA_EXP_REGION8_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM_SHAPER_RAMA_EXP_REGION8_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM_SHAPER_RAMA_EXP_REGION9_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM_SHAPER_RAMA_EXP_REGION9_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM_SHAPER_RAMA_EXP_REGION10_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM_SHAPER_RAMA_EXP_REGION10_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM_SHAPER_RAMA_EXP_REGION11_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM_SHAPER_RAMA_EXP_REGION11_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM_SHAPER_RAMA_EXP_REGION12_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM_SHAPER_RAMA_EXP_REGION12_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM_SHAPER_RAMA_EXP_REGION13_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM_SHAPER_RAMA_EXP_REGION13_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM_SHAPER_RAMA_EXP_REGION14_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM_SHAPER_RAMA_EXP_REGION14_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM_SHAPER_RAMA_EXP_REGION15_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM_SHAPER_RAMA_EXP_REGION15_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM_SHAPER_RAMA_EXP_REGION16_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM_SHAPER_RAMA_EXP_REGION16_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM_SHAPER_RAMA_EXP_REGION17_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM_SHAPER_RAMA_EXP_REGION17_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM_SHAPER_RAMA_EXP_REGION18_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM_SHAPER_RAMA_EXP_REGION18_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM_SHAPER_RAMA_EXP_REGION19_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM_SHAPER_RAMA_EXP_REGION19_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM_SHAPER_RAMA_EXP_REGION20_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM_SHAPER_RAMA_EXP_REGION20_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM_SHAPER_RAMA_EXP_REGION21_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM_SHAPER_RAMA_EXP_REGION21_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM_SHAPER_RAMA_EXP_REGION22_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM_SHAPER_RAMA_EXP_REGION22_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM_SHAPER_RAMA_EXP_REGION23_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM_SHAPER_RAMA_EXP_REGION23_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM_SHAPER_RAMA_EXP_REGION24_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM_SHAPER_RAMA_EXP_REGION24_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM_SHAPER_RAMA_EXP_REGION25_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM_SHAPER_RAMA_EXP_REGION25_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM_SHAPER_RAMA_EXP_REGION26_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM_SHAPER_RAMA_EXP_REGION26_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM_SHAPER_RAMA_EXP_REGION27_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM_SHAPER_RAMA_EXP_REGION27_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM_SHAPER_RAMA_EXP_REGION28_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM_SHAPER_RAMA_EXP_REGION28_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM_SHAPER_RAMA_EXP_REGION29_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM_SHAPER_RAMA_EXP_REGION29_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM_SHAPER_RAMA_EXP_REGION30_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM_SHAPER_RAMA_EXP_REGION30_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM_SHAPER_RAMA_EXP_REGION31_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM_SHAPER_RAMA_EXP_REGION31_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM_SHAPER_RAMA_EXP_REGION32_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM_SHAPER_RAMA_EXP_REGION32_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_B, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_B, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_G, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_G, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_G, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_R, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_R, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_START_CNTL_R, MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_B, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_B, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_G, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_G, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_G, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_G, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_R, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_R, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_END_CNTL_R, MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_R, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM_SHAPER_RAMB_EXP_REGION2_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM_SHAPER_RAMB_EXP_REGION2_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM_SHAPER_RAMB_EXP_REGION3_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM_SHAPER_RAMB_EXP_REGION3_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM_SHAPER_RAMB_EXP_REGION4_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM_SHAPER_RAMB_EXP_REGION4_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM_SHAPER_RAMB_EXP_REGION5_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM_SHAPER_RAMB_EXP_REGION5_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM_SHAPER_RAMB_EXP_REGION6_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM_SHAPER_RAMB_EXP_REGION6_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM_SHAPER_RAMB_EXP_REGION7_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM_SHAPER_RAMB_EXP_REGION7_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM_SHAPER_RAMB_EXP_REGION8_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM_SHAPER_RAMB_EXP_REGION8_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM_SHAPER_RAMB_EXP_REGION9_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM_SHAPER_RAMB_EXP_REGION9_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM_SHAPER_RAMB_EXP_REGION10_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM_SHAPER_RAMB_EXP_REGION10_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM_SHAPER_RAMB_EXP_REGION11_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM_SHAPER_RAMB_EXP_REGION11_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM_SHAPER_RAMB_EXP_REGION12_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM_SHAPER_RAMB_EXP_REGION12_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM_SHAPER_RAMB_EXP_REGION13_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM_SHAPER_RAMB_EXP_REGION13_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM_SHAPER_RAMB_EXP_REGION14_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM_SHAPER_RAMB_EXP_REGION14_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM_SHAPER_RAMB_EXP_REGION15_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM_SHAPER_RAMB_EXP_REGION15_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM_SHAPER_RAMB_EXP_REGION16_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM_SHAPER_RAMB_EXP_REGION16_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM_SHAPER_RAMB_EXP_REGION17_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM_SHAPER_RAMB_EXP_REGION17_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM_SHAPER_RAMB_EXP_REGION18_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM_SHAPER_RAMB_EXP_REGION18_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM_SHAPER_RAMB_EXP_REGION19_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM_SHAPER_RAMB_EXP_REGION19_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM_SHAPER_RAMB_EXP_REGION20_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM_SHAPER_RAMB_EXP_REGION20_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM_SHAPER_RAMB_EXP_REGION21_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM_SHAPER_RAMB_EXP_REGION21_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM_SHAPER_RAMB_EXP_REGION22_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM_SHAPER_RAMB_EXP_REGION22_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM_SHAPER_RAMB_EXP_REGION23_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM_SHAPER_RAMB_EXP_REGION23_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM_SHAPER_RAMB_EXP_REGION24_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM_SHAPER_RAMB_EXP_REGION24_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM_SHAPER_RAMB_EXP_REGION25_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM_SHAPER_RAMB_EXP_REGION25_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM_SHAPER_RAMB_EXP_REGION26_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM_SHAPER_RAMB_EXP_REGION26_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM_SHAPER_RAMB_EXP_REGION27_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM_SHAPER_RAMB_EXP_REGION27_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM_SHAPER_RAMB_EXP_REGION28_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM_SHAPER_RAMB_EXP_REGION28_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM_SHAPER_RAMB_EXP_REGION29_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM_SHAPER_RAMB_EXP_REGION29_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM_SHAPER_RAMB_EXP_REGION30_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM_SHAPER_RAMB_EXP_REGION30_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM_SHAPER_RAMB_EXP_REGION31_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM_SHAPER_RAMB_EXP_REGION31_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM_SHAPER_RAMB_EXP_REGION32_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM_SHAPER_RAMB_EXP_REGION32_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM_SHAPER_RAMB_EXP_REGION33_LUT_OFFSET, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM_SHAPER_RAMB_EXP_REGION33_NUM_SEGMENTS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_MODE, MPC_RMCM_3DLUT_MODE, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_MODE, MPC_RMCM_3DLUT_SIZE, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_MODE, MPC_RMCM_3DLUT_MODE_CURRENT, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_INDEX, MPC_RMCM_3DLUT_INDEX, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_DATA, MPC_RMCM_3DLUT_DATA0, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_DATA, MPC_RMCM_3DLUT_DATA1, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_DATA_30BIT, MPC_RMCM_3DLUT_DATA_30BIT, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM_3DLUT_WRITE_EN_MASK, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM_3DLUT_RAM_SEL, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM_3DLUT_30BIT_EN, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM_3DLUT_READ_SEL, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_NORM_FACTOR, MPC_RMCM_3DLUT_OUT_NORM_FACTOR, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_R, MPC_RMCM_3DLUT_OUT_OFFSET_R, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_R, MPC_RMCM_3DLUT_OUT_SCALE_R, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_G, MPC_RMCM_3DLUT_OUT_OFFSET_G, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_G, MPC_RMCM_3DLUT_OUT_SCALE_G, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_B, MPC_RMCM_3DLUT_OUT_OFFSET_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_OUT_OFFSET_B, MPC_RMCM_3DLUT_OUT_SCALE_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_COEF_FORMAT, MPC_RMCM_GAMUT_REMAP_COEF_FORMAT, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_MODE, MPC_RMCM_GAMUT_REMAP_MODE, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_MODE, MPC_RMCM_GAMUT_REMAP_MODE_CURRENT, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C11_C12_A, MPC_RMCM_GAMUT_REMAP_C11_A, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C11_C12_A, MPC_RMCM_GAMUT_REMAP_C12_A, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C13_C14_A, MPC_RMCM_GAMUT_REMAP_C13_A, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C13_C14_A, MPC_RMCM_GAMUT_REMAP_C14_A, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C21_C22_A, MPC_RMCM_GAMUT_REMAP_C21_A, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C21_C22_A, MPC_RMCM_GAMUT_REMAP_C22_A, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C23_C24_A, MPC_RMCM_GAMUT_REMAP_C23_A, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C23_C24_A, MPC_RMCM_GAMUT_REMAP_C24_A, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C31_C32_A, MPC_RMCM_GAMUT_REMAP_C31_A, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C31_C32_A, MPC_RMCM_GAMUT_REMAP_C32_A, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C33_C34_A, MPC_RMCM_GAMUT_REMAP_C33_A, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C33_C34_A, MPC_RMCM_GAMUT_REMAP_C34_A, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C11_C12_B, MPC_RMCM_GAMUT_REMAP_C11_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C11_C12_B, MPC_RMCM_GAMUT_REMAP_C12_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C13_C14_B, MPC_RMCM_GAMUT_REMAP_C13_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C13_C14_B, MPC_RMCM_GAMUT_REMAP_C14_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C21_C22_B, MPC_RMCM_GAMUT_REMAP_C21_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C21_C22_B, MPC_RMCM_GAMUT_REMAP_C22_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C23_C24_B, MPC_RMCM_GAMUT_REMAP_C23_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C23_C24_B, MPC_RMCM_GAMUT_REMAP_C24_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C31_C32_B, MPC_RMCM_GAMUT_REMAP_C31_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C31_C32_B, MPC_RMCM_GAMUT_REMAP_C32_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C33_C34_B, MPC_RMCM_GAMUT_REMAP_C33_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_GAMUT_REMAP_C33_C34_B, MPC_RMCM_GAMUT_REMAP_C34_B, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_SHAPER_MEM_PWR_FORCE, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_SHAPER_MEM_PWR_DIS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_SHAPER_MEM_LOW_PWR_MODE, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_3DLUT_MEM_PWR_FORCE, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_3DLUT_MEM_PWR_DIS, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_3DLUT_MEM_LOW_PWR_MODE, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_SHAPER_MEM_PWR_STATE, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM_3DLUT_MEM_PWR_STATE, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_FAST_LOAD_SELECT, MPC_RMCM_3DLUT_FL_SEL, mask_sh),\
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_FAST_LOAD_STATUS, MPC_RMCM_3DLUT_FL_DONE, mask_sh), \
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_FAST_LOAD_STATUS, MPC_RMCM_3DLUT_FL_SOFT_UNDERFLOW, mask_sh), \
+ SF(MPC_RMCM0_MPC_RMCM_3DLUT_FAST_LOAD_STATUS, MPC_RMCM_3DLUT_FL_HARD_UNDERFLOW, mask_sh), \
+ SF(MPC_RMCM0_MPC_RMCM_CNTL, MPC_RMCM_CNTL, mask_sh), \
+ SF(MPC_RMCM0_MPC_RMCM_TEST_DEBUG_INDEX, MPC_RMCM_TEST_DEBUG_INDEX, mask_sh), \
+ SF(MPC_RMCM0_MPC_RMCM_TEST_DEBUG_INDEX, MPC_RMCM_TEST_DEBUG_WRITE_EN, mask_sh), \
+ SF(MPC_RMCM0_MPC_RMCM_TEST_DEBUG_DATA, MPC_RMCM_TEST_DEBUG_DATA, mask_sh)
+
+#define MPC_RMCM_REG_LIST_DCN42(inst)\
+ SRII(MPC_RMCM_SHAPER_CONTROL, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_OFFSET_R, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_OFFSET_G, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_OFFSET_B, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_SCALE_R, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_SCALE_G_B, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_LUT_INDEX, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_LUT_DATA, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_START_CNTL_B, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_START_CNTL_G, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_START_CNTL_R, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_END_CNTL_B, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_END_CNTL_G, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_END_CNTL_R, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_0_1, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_2_3, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_4_5, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_6_7, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_8_9, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_10_11, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_12_13, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_14_15, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_16_17, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_18_19, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_20_21, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_22_23, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_24_25, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_26_27, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_28_29, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_30_31, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMA_REGION_32_33, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_START_CNTL_B, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_START_CNTL_G, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_START_CNTL_R, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_END_CNTL_B, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_END_CNTL_G, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_END_CNTL_R, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_0_1, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_2_3, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_4_5, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_6_7, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_8_9, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_10_11, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_12_13, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_14_15, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_16_17, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_18_19, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_20_21, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_22_23, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_24_25, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_26_27, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_28_29, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_30_31, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_SHAPER_RAMB_REGION_32_33, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_3DLUT_MODE, MPC_RMCM, inst), /*TODO: may need to add other 3DLUT regs*/\
+ SRII(MPC_RMCM_3DLUT_INDEX, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_3DLUT_DATA, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_3DLUT_DATA_30BIT, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_3DLUT_READ_WRITE_CONTROL, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_3DLUT_OUT_NORM_FACTOR, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_3DLUT_OUT_OFFSET_R, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_3DLUT_OUT_OFFSET_G, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_3DLUT_OUT_OFFSET_B, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_COEF_FORMAT, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_MODE, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_C11_C12_A, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_C13_C14_A, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_C21_C22_A, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_C23_C24_A, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_C31_C32_A, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_C33_C34_A, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_C11_C12_B, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_C13_C14_B, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_C21_C22_B, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_C23_C24_B, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_C31_C32_B, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_GAMUT_REMAP_C33_C34_B, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_MEM_PWR_CTRL, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_3DLUT_FAST_LOAD_SELECT, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_3DLUT_FAST_LOAD_STATUS, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_CNTL, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_TEST_DEBUG_INDEX, MPC_RMCM, inst),\
+ SRII(MPC_RMCM_TEST_DEBUG_DATA, MPC_RMCM, inst)
+
+
+#define MPC_REG_LIST_DCN42(inst) \
+ MPC_REG_LIST_DCN4_01_RI(inst),\
+ SRII(MPCC_CONTROL2, MPCC, inst)
+
+#define MPC_REG_FIELD_LIST_DCN42(type) \
+ MPC_REG_FIELD_LIST_DCN4_01(type); \
+ type MPCC_MCM_3DLUT_OUT_OFFSET_R;\
+ type MPCC_MCM_3DLUT_OUT_SCALE_R;\
+ type MPCC_MCM_3DLUT_OUT_OFFSET_G;\
+ type MPCC_MCM_3DLUT_OUT_SCALE_G;\
+ type MPCC_MCM_3DLUT_OUT_OFFSET_B;\
+ type MPCC_MCM_3DLUT_OUT_SCALE_B;\
+ type MPC_RMCM_SHAPER_LUT_MODE;\
+ type MPC_RMCM_SHAPER_MODE_CURRENT;\
+ type MPC_RMCM_SHAPER_OFFSET_R;\
+ type MPC_RMCM_SHAPER_OFFSET_G;\
+ type MPC_RMCM_SHAPER_OFFSET_B;\
+ type MPC_RMCM_SHAPER_SCALE_R;\
+ type MPC_RMCM_SHAPER_SCALE_G;\
+ type MPC_RMCM_SHAPER_SCALE_B;\
+ type MPC_RMCM_SHAPER_LUT_INDEX;\
+ type MPC_RMCM_SHAPER_LUT_DATA;\
+ type MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK;\
+ type MPC_RMCM_SHAPER_LUT_WRITE_SEL; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_B; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_B; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_G; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_G;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_R;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION_START_SEGMENT_R;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_B;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_B;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_G;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_G;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_R;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION_END_BASE_R;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION0_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION0_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION1_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION1_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION2_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION2_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION3_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION3_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION4_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION4_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION5_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION5_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION6_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION6_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION7_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION7_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION8_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION8_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION9_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION9_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION10_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION10_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION11_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION11_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION12_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION12_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION13_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION13_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION14_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION14_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION15_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION15_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION16_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION16_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION17_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION17_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION18_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION18_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION19_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION19_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION20_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION20_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION21_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION21_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION22_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION22_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION23_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION23_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION24_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION24_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION25_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION25_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION26_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION26_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION27_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION27_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION28_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION28_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION29_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION29_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION30_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION30_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION31_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION31_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION32_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION32_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION33_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMA_EXP_REGION33_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_B; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_B; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_G; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_G;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_R;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION_START_SEGMENT_R;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_B;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_B;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_G;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_G;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_R;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION_END_BASE_R;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION0_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION0_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION1_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION1_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION2_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION2_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION3_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION3_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION4_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION4_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION5_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION5_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION6_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION6_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION7_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION7_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION8_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION8_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION9_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION9_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION10_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION10_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION11_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION11_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION12_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION12_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION13_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION13_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION14_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION14_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION15_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION15_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION16_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION16_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION17_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION17_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION18_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION18_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION19_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION19_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION20_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION20_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION21_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION21_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION22_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION22_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION23_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION23_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION24_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION24_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION25_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION25_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION26_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION26_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION27_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION27_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION28_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION28_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION29_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION29_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION30_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION30_NUM_SEGMENTS;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION31_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION31_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION32_LUT_OFFSET; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION32_NUM_SEGMENTS; \
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION33_LUT_OFFSET;\
+ type MPC_RMCM_SHAPER_RAMB_EXP_REGION33_NUM_SEGMENTS;\
+ type MPC_RMCM_3DLUT_MODE;\
+ type MPC_RMCM_3DLUT_SIZE;\
+ type MPC_RMCM_3DLUT_MODE_CURRENT;\
+ type MPC_RMCM_3DLUT_INDEX; \
+ type MPC_RMCM_3DLUT_DATA0; \
+ type MPC_RMCM_3DLUT_DATA1; \
+ type MPC_RMCM_3DLUT_DATA_30BIT; \
+ type MPC_RMCM_3DLUT_WRITE_EN_MASK;\
+ type MPC_RMCM_3DLUT_RAM_SEL;\
+ type MPC_RMCM_3DLUT_30BIT_EN;\
+ type MPC_RMCM_3DLUT_READ_SEL;\
+ type MPC_RMCM_3DLUT_OUT_NORM_FACTOR;\
+ type MPC_RMCM_3DLUT_OUT_OFFSET_R;\
+ type MPC_RMCM_3DLUT_OUT_SCALE_R; \
+ type MPC_RMCM_3DLUT_OUT_OFFSET_G; \
+ type MPC_RMCM_3DLUT_OUT_SCALE_G; \
+ type MPC_RMCM_3DLUT_OUT_OFFSET_B; \
+ type MPC_RMCM_3DLUT_OUT_SCALE_B;\
+ type MPC_RMCM_GAMUT_REMAP_COEF_FORMAT;\
+ type MPC_RMCM_GAMUT_REMAP_MODE;\
+ type MPC_RMCM_GAMUT_REMAP_MODE_CURRENT;\
+ type MPC_RMCM_GAMUT_REMAP_C11_A;\
+ type MPC_RMCM_GAMUT_REMAP_C12_A;\
+ type MPC_RMCM_GAMUT_REMAP_C13_A; \
+ type MPC_RMCM_GAMUT_REMAP_C14_A; \
+ type MPC_RMCM_GAMUT_REMAP_C21_A; \
+ type MPC_RMCM_GAMUT_REMAP_C22_A; \
+ type MPC_RMCM_GAMUT_REMAP_C23_A;\
+ type MPC_RMCM_GAMUT_REMAP_C24_A;\
+ type MPC_RMCM_GAMUT_REMAP_C31_A;\
+ type MPC_RMCM_GAMUT_REMAP_C32_A;\
+ type MPC_RMCM_GAMUT_REMAP_C33_A;\
+ type MPC_RMCM_GAMUT_REMAP_C34_A;\
+ type MPC_RMCM_GAMUT_REMAP_C11_B;\
+ type MPC_RMCM_GAMUT_REMAP_C12_B;\
+ type MPC_RMCM_GAMUT_REMAP_C13_B; \
+ type MPC_RMCM_GAMUT_REMAP_C14_B; \
+ type MPC_RMCM_GAMUT_REMAP_C21_B; \
+ type MPC_RMCM_GAMUT_REMAP_C22_B; \
+ type MPC_RMCM_GAMUT_REMAP_C23_B;\
+ type MPC_RMCM_GAMUT_REMAP_C24_B;\
+ type MPC_RMCM_GAMUT_REMAP_C31_B;\
+ type MPC_RMCM_GAMUT_REMAP_C32_B;\
+ type MPC_RMCM_GAMUT_REMAP_C33_B;\
+ type MPC_RMCM_GAMUT_REMAP_C34_B;\
+ type MPC_RMCM_SHAPER_MEM_PWR_FORCE; \
+ type MPC_RMCM_SHAPER_MEM_PWR_DIS; \
+ type MPC_RMCM_SHAPER_MEM_LOW_PWR_MODE; \
+ type MPC_RMCM_3DLUT_MEM_PWR_FORCE;\
+ type MPC_RMCM_3DLUT_MEM_PWR_DIS;\
+ type MPC_RMCM_3DLUT_MEM_LOW_PWR_MODE;\
+ type MPC_RMCM_SHAPER_MEM_PWR_STATE;\
+ type MPC_RMCM_3DLUT_MEM_PWR_STATE;\
+ type MPC_RMCM_3DLUT_FL_SEL;\
+ type MPC_RMCM_3DLUT_FL_DONE; \
+ type MPC_RMCM_3DLUT_FL_SOFT_UNDERFLOW; \
+ type MPC_RMCM_3DLUT_FL_HARD_UNDERFLOW; \
+ type MPC_RMCM_CNTL; \
+ type MPC_RMCM_TEST_DEBUG_INDEX;\
+ type MPC_RMCM_TEST_DEBUG_WRITE_EN;\
+ type MPC_RMCM_TEST_DEBUG_DATA
+
+#define MPC_REG_VARIABLE_LIST_DCN42 \
+ MPC_REG_VARIABLE_LIST_DCN4_01 \
+ uint32_t MPCC_CONTROL2[MAX_MPCC];\
+ uint32_t MPC_RMCM_SHAPER_CONTROL[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_OFFSET_R[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_OFFSET_G[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_OFFSET_B[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_SCALE_R[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_SCALE_G_B[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_LUT_INDEX[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_LUT_DATA[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_LUT_WRITE_EN_MASK[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_START_CNTL_B[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_START_CNTL_G[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_START_CNTL_R[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_END_CNTL_B[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_END_CNTL_G[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_END_CNTL_R[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_0_1[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_2_3[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_4_5[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_6_7[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_8_9[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_10_11[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_12_13[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_14_15[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_16_17[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_18_19[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_20_21[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_22_23[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_24_25[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_26_27[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_28_29[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_30_31[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMA_REGION_32_33[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_START_CNTL_B[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_START_CNTL_G[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_START_CNTL_R[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_END_CNTL_B[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_END_CNTL_G[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_END_CNTL_R[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_0_1[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_2_3[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_4_5[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_6_7[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_8_9[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_10_11[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_12_13[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_14_15[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_16_17[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_18_19[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_20_21[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_22_23[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_24_25[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_26_27[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_28_29[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_30_31[MAX_MPCC]; \
+ uint32_t MPC_RMCM_SHAPER_RAMB_REGION_32_33[MAX_MPCC]; \
+ uint32_t MPC_RMCM_3DLUT_MODE[MAX_MPCC]; \
+ uint32_t MPC_RMCM_3DLUT_INDEX[MAX_MPCC]; \
+ uint32_t MPC_RMCM_3DLUT_DATA[MAX_MPCC]; \
+ uint32_t MPC_RMCM_3DLUT_DATA_30BIT[MAX_MPCC]; \
+ uint32_t MPC_RMCM_3DLUT_READ_WRITE_CONTROL[MAX_MPCC]; \
+ uint32_t MPC_RMCM_3DLUT_OUT_NORM_FACTOR[MAX_MPCC]; \
+ uint32_t MPC_RMCM_3DLUT_OUT_OFFSET_R[MAX_MPCC]; \
+ uint32_t MPC_RMCM_3DLUT_OUT_OFFSET_G[MAX_MPCC]; \
+ uint32_t MPC_RMCM_3DLUT_OUT_OFFSET_B[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_COEF_FORMAT[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_MODE[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_C11_C12_A[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_C13_C14_A[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_C21_C22_A[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_C23_C24_A[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_C31_C32_A[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_C33_C34_A[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_C11_C12_B[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_C13_C14_B[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_C21_C22_B[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_C23_C24_B[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_C31_C32_B[MAX_MPCC]; \
+ uint32_t MPC_RMCM_GAMUT_REMAP_C33_C34_B[MAX_MPCC]; \
+ uint32_t MPC_RMCM_MEM_PWR_CTRL[MAX_MPCC]; \
+ uint32_t MPC_RMCM_3DLUT_FAST_LOAD_SELECT[MAX_MPCC]; \
+ uint32_t MPC_RMCM_3DLUT_FAST_LOAD_STATUS[MAX_MPCC]; \
+ uint32_t MPC_RMCM_CNTL[MAX_MPCC]; \
+ uint32_t MPC_RMCM_TEST_DEBUG_INDEX[MAX_MPCC]; \
+ uint32_t MPC_RMCM_TEST_DEBUG_DATA[MAX_MPCC]
+
+struct dcn42_mpc_shift {
+ MPC_REG_FIELD_LIST_DCN42(uint8_t);
+};
+
+struct dcn42_mpc_mask {
+ MPC_REG_FIELD_LIST_DCN42(uint32_t);
+};
+
+struct dcn42_mpc_registers {
+ MPC_REG_VARIABLE_LIST_DCN42;
+};
+
+struct dcn42_mpc {
+ struct mpc base;
+
+ int mpcc_in_use_mask;
+ int num_mpcc;
+ const struct dcn42_mpc_registers *mpc_regs;
+ const struct dcn42_mpc_shift *mpc_shift;
+ const struct dcn42_mpc_mask *mpc_mask;
+ int num_rmu;
+};
+void dcn42_mpc_construct(struct dcn42_mpc *mpc401,
+ struct dc_context *ctx,
+ const struct dcn42_mpc_registers *mpc_regs,
+ const struct dcn42_mpc_shift *mpc_shift,
+ const struct dcn42_mpc_mask *mpc_mask,
+ int num_mpcc,
+ int num_rmu);
+
+void mpc42_init_mpcc(struct mpcc *mpcc, int mpcc_inst);
+
+/* RMCM */
+void mpc42_program_rmcm_shaper_lut(
+ struct mpc *mpc,
+ const struct pwl_result_data *rgb,
+ uint32_t num,
+ uint32_t mpcc_id);
+void mpc42_program_rmcm_shaper_lutb_settings(
+ struct mpc *mpc,
+ const struct pwl_params *params,
+ uint32_t mpcc_id);
+void mpc42_program_rmcm_shaper_luta_settings(
+ struct mpc *mpc,
+ const struct pwl_params *params,
+ uint32_t mpcc_id);
+void mpc42_configure_rmcm_shaper_lut(
+ struct mpc *mpc,
+ bool is_ram_a,
+ uint32_t mpcc_id);
+void mpc42_power_on_rmcm_shaper_3dlut(
+ struct mpc *mpc,
+ uint32_t mpcc_id,
+ bool power_on);
+void mpc42_enable_3dlut_fl(
+ struct mpc *mpc,
+ bool enable,
+ int mpcc_id);
+void mpc42_update_3dlut_fast_load_select(
+ struct mpc *mpc,
+ int mpcc_id,
+ int hubp_idx);
+void mpc42_populate_rmcm_lut(
+ struct mpc *mpc,
+ const union mcm_lut_params params,
+ bool lut_bank_a,
+ int mpcc_id);
+void mpc42_program_rmcm_lut_read_write_control(
+ struct mpc *mpc,
+ const enum MCM_LUT_ID id,
+ bool lut_bank_a,
+ bool enabled,
+ int mpcc_id);
+void mpc42_program_lut_mode(
+ struct mpc *mpc,
+ bool enable,
+ bool lut_bank_a,
+ int mpcc_id);
+void mpc42_program_rmcm_3dlut_size(
+ struct mpc *mpc,
+ const enum dc_cm_lut_size size,
+ int mpcc_id);
+void mpc42_program_rmcm_3dlut_fast_load_bias_scale(
+ struct mpc *mpc,
+ uint16_t bias,
+ uint16_t scale,
+ int mpcc_id);
+void mpc42_program_rmcm_bit_depth(
+ struct mpc *mpc,
+ uint16_t bit_depth,
+ int mpcc_id);
+
+void mpc42_set_fl_config(
+ struct mpc *mpc,
+ struct mpc_fl_3dlut_config *cfg,
+ int mpcc_id);
+
+void mpc42_read_mpcc_state(
+ struct mpc *mpc,
+ int mpcc_inst,
+ struct mpcc_state *s);
+
+void mpc42_update_blending(
+ struct mpc *mpc,
+ struct mpcc_blnd_cfg *blnd_cfg,
+ int mpcc_id);
+
+#endif
diff --git a/drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c
index 45d418636d0c..b49bd155cad4 100644
--- a/drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c
+++ b/drivers/gpu/drm/amd/display/dc/opp/dcn10/dcn10_opp.c
@@ -250,6 +250,7 @@ void opp1_set_dyn_expansion(
enum dc_color_depth color_dpth,
enum signal_type signal)
{
+ (void)color_sp;
struct dcn10_opp *oppn10 = TO_DCN10_OPP(opp);
REG_UPDATE_2(FMT_DYNAMIC_EXP_CNTL,
diff --git a/drivers/gpu/drm/amd/display/dc/optc/Makefile b/drivers/gpu/drm/amd/display/dc/optc/Makefile
index 29fb610c8660..06c98d70eabc 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/optc/Makefile
@@ -104,11 +104,19 @@ AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN35)
###############################################################################
-###############################################################################
OPTC_DCN401 = dcn401_optc.o
AMD_DAL_OPTC_DCN401 = $(addprefix $(AMDDALPATH)/dc/optc/dcn401/,$(OPTC_DCN401))
AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN401)
+
+###############################################################################
+
+OPTC_DCN42 = dcn42_optc.o
+
+AMD_DAL_OPTC_DCN42 = $(addprefix $(AMDDALPATH)/dc/optc/dcn42/,$(OPTC_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_OPTC_DCN42)
+
endif
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 6f7b0f816f2a..9e66b9b97c63 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
@@ -164,6 +164,7 @@ void optc1_program_timing(
const enum signal_type signal,
bool use_vbios)
{
+ (void)use_vbios;
struct dc_crtc_timing patched_crtc_timing;
uint32_t asic_blank_end;
uint32_t asic_blank_start;
@@ -855,6 +856,8 @@ void optc1_set_early_control(
struct timing_generator *optc,
uint32_t early_cntl)
{
+ (void)optc;
+ (void)early_cntl;
/* asic design change, do not need this control
* empty for share caller logic
*/
@@ -1249,6 +1252,7 @@ void optc1_get_crtc_scanoutpos(
static void optc1_enable_stereo(struct timing_generator *optc,
const struct dc_crtc_timing *timing, struct crtc_stereo_flags *flags)
{
+ (void)timing;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
if (flags) {
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 0b3f974f452e..138081e6cc97 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2012-15 Advanced Micro Devices, Inc.
+ * Copyright 2012-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -218,7 +218,7 @@
uint32_t OTG_CRC_SIG_BLUE_CONTROL_MASK; \
uint32_t OTG_CRC_SIG_RED_GREEN_MASK; \
uint32_t OTG_DLPC_CONTROL; \
- uint32_t OTG_DRR_CONTROL2; \
+ uint32_t OTG_DRR_CONTOL2; \
uint32_t OTG_DRR_TIMING_INT_STATUS; \
uint32_t OTG_GLOBAL_CONTROL3; \
uint32_t OTG_GLOBAL_SYNC_STATUS; \
@@ -253,8 +253,20 @@
uint32_t OTG_CRC1_DATA_B32
+#define OPTC_REG_VARIABLE_LIST_DCN42 \
+ uint32_t OTG_PWA_FRAME_SYNC_CONTROL; \
+ uint32_t OTG_CRC0_DATA_R; \
+ uint32_t OTG_CRC1_DATA_R; \
+ uint32_t OTG_CRC2_DATA_R; \
+ uint32_t OTG_CRC3_DATA_R; \
+ uint32_t OTG_CRC0_DATA_G; \
+ uint32_t OTG_CRC1_DATA_G; \
+ uint32_t OTG_CRC2_DATA_G; \
+ uint32_t OTG_CRC3_DATA_G
+
struct dcn_optc_registers {
OPTC_REG_VARIABLE_LIST_DCN;
+ OPTC_REG_VARIABLE_LIST_DCN42;
};
#define TG_COMMON_MASK_SH_LIST_DCN(mask_sh)\
@@ -664,6 +676,10 @@ struct dcn_optc_registers {
type OTG_V_COUNT_STOP_TIMER;
#define TG_REG_FIELD_LIST_DCN3_6(type) \
+ type OPTC_RSMU_UNDERFLOW_CLEAR;\
+ type OPTC_RSMU_UNDERFLOW_OCCURRED_STATUS;\
+ type OPTC_RSMU_UNDERFLOW_INT_EN;\
+ type OPTC_RSMU_UNDERFLOW_INT_STATUS;\
type OTG_CRC_POLY_SEL; \
type CRC0_R_CR32; \
type CRC0_G_Y32; \
@@ -679,6 +695,10 @@ struct dcn_optc_registers {
type OTG_UNBLANK;\
type OTG_PSTATE_ALLOW_WIDTH_MIN;
+#define TG_REG_FIELD_LIST_DCN42(type) \
+ type OTG_PWA_FRAME_SYNC_EN;\
+ type OTG_PWA_FRAME_SYNC_VCOUNT_MODE;\
+ type OTG_PWA_FRAME_SYNC_LINE;
struct dcn_optc_shift {
TG_REG_FIELD_LIST(uint8_t)
@@ -687,6 +707,7 @@ struct dcn_optc_shift {
TG_REG_FIELD_LIST_DCN3_5(uint8_t)
TG_REG_FIELD_LIST_DCN3_6(uint8_t)
TG_REG_FIELD_LIST_DCN401(uint8_t)
+ TG_REG_FIELD_LIST_DCN42(uint8_t)
};
struct dcn_optc_mask {
@@ -696,6 +717,7 @@ struct dcn_optc_mask {
TG_REG_FIELD_LIST_DCN3_5(uint32_t)
TG_REG_FIELD_LIST_DCN3_6(uint32_t)
TG_REG_FIELD_LIST_DCN401(uint32_t)
+ TG_REG_FIELD_LIST_DCN42(uint32_t)
};
void dcn10_timing_generator_init(struct optc *optc);
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c
index e7a90a437fff..39ce4d4a61a1 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c
@@ -181,6 +181,7 @@ void optc2_set_odm_bypass(struct timing_generator *optc,
void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int segment_width, int last_segment_width)
{
+ (void)last_segment_width;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t memory_mask;
@@ -261,6 +262,7 @@ static void optc2_align_vblanks(
uint8_t master_clock_divider,
uint8_t slave_clock_divider)
{
+ (void)slave_clock_divider;
/* accessing slave OTG registers */
struct optc *optc1 = DCN10TG_FROM_TG(optc_slave);
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c
index ee4665aa49e9..d72574db1f07 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c
@@ -218,6 +218,7 @@ void optc3_set_odm_bypass(struct timing_generator *optc,
void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int segment_width, int last_segment_width)
{
+ (void)last_segment_width;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t memory_mask = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c
index c6417538090f..5f53f8747812 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c
@@ -43,6 +43,7 @@
static void optc31_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int segment_width, int last_segment_width)
{
+ (void)last_segment_width;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t memory_mask = 0;
int mem_count_per_opp = (segment_width + 2559) / 2560;
@@ -363,7 +364,7 @@ void optc31_read_reg_state(struct timing_generator *optc, struct dcn_optc_reg_st
optc_reg_state->otg_crc3_data_rg = REG_READ(OTG_CRC3_DATA_RG);
optc_reg_state->otg_dlpc_control = REG_READ(OTG_DLPC_CONTROL);
optc_reg_state->otg_double_buffer_control = REG_READ(OTG_DOUBLE_BUFFER_CONTROL);
- optc_reg_state->otg_drr_control2 = REG_READ(OTG_DRR_CONTROL2);
+ optc_reg_state->otg_drr_control2 = REG_READ(OTG_DRR_CONTOL2);
optc_reg_state->otg_drr_control = REG_READ(OTG_DRR_CONTROL);
optc_reg_state->otg_drr_timing_int_status = REG_READ(OTG_DRR_TIMING_INT_STATUS);
optc_reg_state->otg_drr_trigger_window = REG_READ(OTG_DRR_TRIGGER_WINDOW);
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c
index 43ff957288b2..a7cf34937b2f 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c
@@ -50,6 +50,7 @@
static void optc314_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int segment_width, int last_segment_width)
{
+ (void)last_segment_width;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t memory_mask = 0;
int h_active = segment_width * opp_cnt;
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
index 3dcb0d0c931c..60e546b69a05 100644
--- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
@@ -45,6 +45,7 @@
static void optc32_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int segment_width, int last_segment_width)
{
+ (void)last_segment_width;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t memory_mask = 0;
int h_active = segment_width * opp_cnt;
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 5aafd0eedf66..a880e4a6d165 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
@@ -58,6 +58,7 @@
static void optc35_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
int segment_width, int last_segment_width)
{
+ (void)last_segment_width;
struct optc *optc1 = DCN10TG_FROM_TG(optc);
uint32_t memory_mask = 0;
int h_active = segment_width * opp_cnt;
diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c
new file mode 100644
index 000000000000..ed66a2bbb8ae
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.c
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dcn42_optc.h"
+#include "dcn30/dcn30_optc.h"
+#include "dcn31/dcn31_optc.h"
+#include "dcn32/dcn32_optc.h"
+#include "dcn35/dcn35_optc.h"
+#include "dcn401/dcn401_optc.h"
+#include "reg_helper.h"
+#include "dc.h"
+#include "dcn_calc_math.h"
+#include "dc_dmub_srv.h"
+#include "dc_trace.h"
+
+#define REG(reg)\
+ optc1->tg_regs->reg
+
+#define CTX \
+ optc1->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+ optc1->tg_shift->field_name, optc1->tg_mask->field_name
+
+/*
+ * optc42_get_crc - Capture CRC result per component
+ *
+ * @optc: timing_generator instance.
+ * @r_cr: 16-bit primary CRC signature for red data.
+ * @g_y: 16-bit primary CRC signature for green data.
+ * @b_cb: 16-bit primary CRC signature for blue data.
+ *
+ * This function reads the CRC signature from the OPTC registers. Notice that
+ * we have three registers to keep the CRC result per color component (RGB).
+ *
+ * Returns:
+ * If CRC is disabled, return false; otherwise, return true, and the CRC
+ * results in the parameters.
+ */
+
+static bool optc42_get_crc(struct timing_generator *optc, uint8_t idx,
+ uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb)
+{
+ uint32_t field = 0;
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+ REG_GET(OTG_CRC_CNTL, OTG_CRC_EN, &field);
+
+ /* Early return if CRC is not enabled for this CRTC */
+ if (!field)
+ return false;
+
+
+ switch (idx) {
+ case 0:
+ /* OTG_CRC0_DATA_RG has the CRC16 results for the red component */
+ REG_GET(OTG_CRC0_DATA_R,
+ CRC0_R_CR, r_cr);
+
+ /* OTG_CRC0_DATA_RG has the CRC16 results for the green component */
+ REG_GET(OTG_CRC0_DATA_G,
+ CRC0_G_Y, g_y);
+
+ /* OTG_CRC0_DATA_B has the CRC16 results for the blue component */
+ REG_GET(OTG_CRC0_DATA_B,
+ CRC0_B_CB, b_cb);
+ break;
+ case 1:
+ /* OTG_CRC1_DATA_RG has the CRC16 results for the red component */
+ REG_GET(OTG_CRC1_DATA_R,
+ CRC0_R_CR, r_cr);
+
+ /* OTG_CRC1_DATA_RG has the CRC16 results for the green component */
+ REG_GET(OTG_CRC1_DATA_G,
+ CRC0_G_Y, g_y);
+
+ /* OTG_CRC1_DATA_B has the CRC16 results for the blue component */
+ REG_GET(OTG_CRC1_DATA_B,
+ CRC0_B_CB, b_cb);
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+void optc42_enable_pwa(struct timing_generator *optc, struct otc_pwa_frame_sync *pwa_sync_param)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+ /*VCOUNT_MODE :
+ 00 OTG_PWA_FRAME_SYNC_VCOUNT_0 Vcount counting from VSYNC.
+ 01 OTG_PWA_FRAME_SYNC_VCOUNT_1 Vcount counting from VSTARTUP.*/
+
+ if (pwa_sync_param == NULL)
+ return;
+ if (optc1->base.ctx->dc->debug.enable_otg_frame_sync_pwa) {
+ /*take mode 1, use line number from vstartup to get output frame as earlier as possible*/
+ REG_UPDATE_3(OTG_PWA_FRAME_SYNC_CONTROL,
+ OTG_PWA_FRAME_SYNC_EN, 1,
+ OTG_PWA_FRAME_SYNC_VCOUNT_MODE, pwa_sync_param->pwa_sync_mode,
+ OTG_PWA_FRAME_SYNC_LINE, pwa_sync_param->pwa_frame_sync_line_offset);
+ }
+}
+void optc42_disable_pwa(struct timing_generator *optc)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+ REG_UPDATE(OTG_PWA_FRAME_SYNC_CONTROL,
+ OTG_PWA_FRAME_SYNC_EN, 0);
+}
+void optc42_clear_optc_underflow(struct timing_generator *optc)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+ REG_UPDATE(OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, 1);
+ REG_UPDATE(OPTC_RSMU_UNDERFLOW, OPTC_RSMU_UNDERFLOW_CLEAR, 1);
+}
+bool optc42_is_optc_underflow_occurred(struct timing_generator *optc)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+ uint32_t underflow_occurred = 0, rsmu_underflow_occurred = 0;
+
+ REG_GET(OPTC_INPUT_GLOBAL_CONTROL,
+ OPTC_UNDERFLOW_OCCURRED_STATUS,
+ &underflow_occurred);
+
+ REG_GET(OPTC_RSMU_UNDERFLOW,
+ OPTC_RSMU_UNDERFLOW_OCCURRED_STATUS,
+ &rsmu_underflow_occurred);
+ return (underflow_occurred == 1 || rsmu_underflow_occurred);
+}
+/* disable_crtc */
+bool optc42_disable_crtc(struct timing_generator *optc)
+{
+ optc401_disable_crtc(optc);
+ optc42_clear_optc_underflow(optc);
+
+ return true;
+}
+static void optc42_set_timing_double_buffer(struct timing_generator *optc, bool enable)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+ uint32_t mode = enable ? 2 : 0;
+ /* actually we have 4 modes now, use as the same as previous dcn3x
+ * 00 OTG_DOUBLE_BUFFER_CONTROL_OTG_DRR_TIMING_DBUF_UPDATE_MODE_0 Double buffer update occurs at any time in a frame.
+ * 01 OTG_DOUBLE_BUFFER_CONTROL_OTG_DRR_TIMING_DBUF_UPDATE_MODE_1 Double buffer update occurs at OTG start of frame.
+ * 02 OTG_DOUBLE_BUFFER_CONTROL_OTG_DRR_TIMING_DBUF_UPDATE_MODE_2 Double buffer occurs DP start of frame.
+ * 03 OTG_DOUBLE_BUFFER_CONTROL_OTG_DRR_TIMING_DBUF_UPDATE_MODE_3 Reserved.
+ */
+
+ REG_UPDATE(OTG_DOUBLE_BUFFER_CONTROL,
+ OTG_DRR_TIMING_DBUF_UPDATE_MODE, mode);
+}
+void optc42_tg_init(struct timing_generator *optc)
+{
+ optc42_set_timing_double_buffer(optc, true);
+ optc42_clear_optc_underflow(optc);
+}
+
+void optc42_lock_doublebuffer_enable(struct timing_generator *optc)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+ uint32_t v_blank_start = 0;
+ uint32_t v_blank_end = 0;
+ uint32_t h_blank_start = 0;
+ uint32_t h_blank_end = 0;
+
+ REG_GET_2(OTG_V_BLANK_START_END,
+ OTG_V_BLANK_START, &v_blank_start,
+ OTG_V_BLANK_END, &v_blank_end);
+ REG_GET_2(OTG_H_BLANK_START_END,
+ OTG_H_BLANK_START, &h_blank_start,
+ OTG_H_BLANK_END, &h_blank_end);
+
+ REG_UPDATE_2(OTG_GLOBAL_CONTROL1,
+ MASTER_UPDATE_LOCK_DB_START_Y, v_blank_start,
+ MASTER_UPDATE_LOCK_DB_END_Y, v_blank_start);
+ REG_UPDATE_2(OTG_GLOBAL_CONTROL4,
+ DIG_UPDATE_POSITION_X, 20,
+ DIG_UPDATE_POSITION_Y, v_blank_start);
+ REG_UPDATE_3(OTG_GLOBAL_CONTROL0,
+ MASTER_UPDATE_LOCK_DB_START_X, h_blank_start - 200 - 1,
+ MASTER_UPDATE_LOCK_DB_END_X, h_blank_end,
+ MASTER_UPDATE_LOCK_DB_EN, 1);
+ REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 1);
+
+ REG_SET_3(OTG_VUPDATE_KEEPOUT, 0,
+ MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0,
+ MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, 100,
+ OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1);
+
+ TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
+}
+
+static struct timing_generator_funcs dcn42_tg_funcs = {
+ .validate_timing = optc1_validate_timing,
+ .program_timing = optc1_program_timing,
+ .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
+ .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
+ .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
+ .program_global_sync = optc401_program_global_sync,
+ .enable_crtc = optc401_enable_crtc,
+ .disable_crtc = optc42_disable_crtc,
+ .phantom_crtc_post_enable = optc401_phantom_crtc_post_enable,
+ .disable_phantom_crtc = optc401_disable_phantom_otg,
+ /* used by enable_timing_synchronization. Not need for FPGA */
+ .is_counter_moving = optc1_is_counter_moving,
+ .get_position = optc1_get_position,
+ .get_frame_count = optc1_get_vblank_counter,
+ .get_scanoutpos = optc1_get_crtc_scanoutpos,
+ .get_otg_active_size = optc1_get_otg_active_size,
+ .set_early_control = optc1_set_early_control,
+ /* used by enable_timing_synchronization. Not need for FPGA */
+ .wait_for_state = optc1_wait_for_state,
+ .set_blank_color = optc3_program_blank_color,
+ .did_triggered_reset_occur = optc1_did_triggered_reset_occur,
+ .triplebuffer_lock = optc3_triplebuffer_lock,
+ .triplebuffer_unlock = optc2_triplebuffer_unlock,
+ .enable_reset_trigger = optc1_enable_reset_trigger,
+ .enable_crtc_reset = optc1_enable_crtc_reset,
+ .disable_reset_trigger = optc1_disable_reset_trigger,
+ .lock = optc3_lock,
+ .unlock = optc1_unlock,
+ .lock_doublebuffer_enable = optc42_lock_doublebuffer_enable,
+ .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,
+ .enable_optc_clock = optc1_enable_optc_clock,
+ .set_drr = optc401_set_drr,
+ .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
+ .set_vtotal_min_max = optc401_set_vtotal_min_max,
+ .set_static_screen_control = optc1_set_static_screen_control,
+ .program_stereo = optc1_program_stereo,
+ .is_stereo_left_eye = optc1_is_stereo_left_eye,
+ .tg_init = optc42_tg_init,
+ .is_tg_enabled = optc1_is_tg_enabled,
+ .is_optc_underflow_occurred = optc42_is_optc_underflow_occurred,
+ .clear_optc_underflow = optc42_clear_optc_underflow,
+ .setup_global_swap_lock = NULL,
+ .get_crc = optc42_get_crc,
+ .configure_crc = optc35_configure_crc,
+ .set_dsc_config = optc3_set_dsc_config,
+ .get_dsc_status = optc2_get_dsc_status,
+ .set_dwb_source = NULL,
+ .set_odm_bypass = optc401_set_odm_bypass,
+ .set_odm_combine = optc401_set_odm_combine,
+ .wait_odm_doublebuffer_pending_clear = optc32_wait_odm_doublebuffer_pending_clear,
+ .set_h_timing_div_manual_mode = optc401_set_h_timing_div_manual_mode,
+ .get_optc_source = optc2_get_optc_source,
+ .wait_otg_disable = optc35_wait_otg_disable,
+ .set_out_mux = optc401_set_out_mux,
+ .set_drr_trigger_window = optc3_set_drr_trigger_window,
+ .set_vtotal_change_limit = optc3_set_vtotal_change_limit,
+ .set_gsl = optc2_set_gsl,
+ .set_gsl_source_select = optc2_set_gsl_source_select,
+ .set_vtg_params = optc1_set_vtg_params,
+ .program_manual_trigger = optc2_program_manual_trigger,
+ .setup_manual_trigger = optc2_setup_manual_trigger,
+ .get_hw_timing = optc1_get_hw_timing,
+ .init_odm = optc3_init_odm,
+ .set_long_vtotal = optc35_set_long_vtotal,
+ .is_two_pixels_per_container = optc1_is_two_pixels_per_container,
+ .get_optc_double_buffer_pending = optc3_get_optc_double_buffer_pending,
+ .get_otg_double_buffer_pending = optc3_get_otg_update_pending,
+ .get_pipe_update_pending = optc3_get_pipe_update_pending,
+ .set_vupdate_keepout = optc401_set_vupdate_keepout,
+ .wait_update_lock_status = optc401_wait_update_lock_status,
+ .optc_read_reg_state = optc31_read_reg_state,
+ .read_otg_state = optc31_read_otg_state,
+ .enable_otg_pwa = optc42_enable_pwa,
+ .disable_otg_pwa = optc42_disable_pwa,
+};
+
+void dcn42_timing_generator_init(struct optc *optc1)
+{
+ optc1->base.funcs = &dcn42_tg_funcs;
+
+ optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
+ optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
+
+ optc1->min_h_blank = 32;
+ optc1->min_v_blank = 3;
+ optc1->min_v_blank_interlace = 5;
+ optc1->min_h_sync_width = 4;
+ optc1->min_v_sync_width = 1;
+ optc1->max_frame_count = 0xFFFFFF;
+
+ dcn35_timing_generator_set_fgcg(
+ optc1, CTX->dc->debug.enable_fine_grain_clock_gating.bits.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
new file mode 100644
index 000000000000..fc7192f01b33
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/optc/dcn42/dcn42_optc.h
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2024 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef __DC_OPTC_DCN42_H__
+#define __DC_OPTC_DCN42_H__
+
+#include "dcn10/dcn10_optc.h"
+
+#define OPTC_COMMON_MASK_SH_LIST_DCN42(mask_sh)\
+ SF(OTG0_OTG_VSTARTUP_PARAM, VSTARTUP_START, mask_sh),\
+ SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_OFFSET, mask_sh),\
+ SF(OTG0_OTG_VUPDATE_PARAM, VUPDATE_WIDTH, mask_sh),\
+ SF(OTG0_OTG_VREADY_PARAM, VREADY_OFFSET, mask_sh),\
+ SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\
+ SF(OTG0_OTG_MASTER_UPDATE_LOCK, UPDATE_LOCK_STATUS, mask_sh),\
+ SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_START_X, mask_sh),\
+ SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_END_X, mask_sh),\
+ SF(OTG0_OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, mask_sh),\
+ SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_START_Y, mask_sh),\
+ SF(OTG0_OTG_GLOBAL_CONTROL1, MASTER_UPDATE_LOCK_DB_END_Y, mask_sh),\
+ SF(OTG0_OTG_GLOBAL_CONTROL2, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\
+ SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_X, mask_sh),\
+ SF(OTG0_OTG_GLOBAL_CONTROL4, DIG_UPDATE_POSITION_Y, mask_sh),\
+ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\
+ SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\
+ SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_START, mask_sh),\
+ SF(OTG0_OTG_H_BLANK_START_END, OTG_H_BLANK_END, mask_sh),\
+ SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_START, mask_sh),\
+ SF(OTG0_OTG_H_SYNC_A, OTG_H_SYNC_A_END, mask_sh),\
+ SF(OTG0_OTG_H_SYNC_A_CNTL, OTG_H_SYNC_A_POL, mask_sh),\
+ SF(OTG0_OTG_V_TOTAL, OTG_V_TOTAL, mask_sh),\
+ SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_START, mask_sh),\
+ SF(OTG0_OTG_V_BLANK_START_END, OTG_V_BLANK_END, mask_sh),\
+ SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_START, mask_sh),\
+ SF(OTG0_OTG_V_SYNC_A, OTG_V_SYNC_A_END, mask_sh),\
+ SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_A_POL, mask_sh),\
+ SF(OTG0_OTG_V_SYNC_A_CNTL, OTG_V_SYNC_MODE, mask_sh),\
+ SF(OTG0_OTG_CONTROL, OTG_CURRENT_MASTER_EN_STATE, mask_sh),\
+ SF(OTG0_OTG_CONTROL, OTG_MASTER_EN, mask_sh),\
+ SF(OTG0_OTG_CONTROL, OTG_START_POINT_CNTL, mask_sh),\
+ SF(OTG0_OTG_CONTROL, OTG_DISABLE_POINT_CNTL, mask_sh),\
+ SF(OTG0_OTG_CONTROL, OTG_FIELD_NUMBER_CNTL, mask_sh),\
+ SF(OTG0_OTG_CONTROL, OTG_OUT_MUX, mask_sh),\
+ SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EN, mask_sh),\
+ SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_LINE_NUM, mask_sh),\
+ SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_SYNC_OUTPUT_POLARITY, mask_sh),\
+ SF(OTG0_OTG_STEREO_CONTROL, OTG_STEREO_EYE_FLAG_POLARITY, mask_sh),\
+ SF(OTG0_OTG_STEREO_CONTROL, OTG_DISABLE_STEREOSYNC_OUTPUT_FOR_DP, mask_sh),\
+ SF(OTG0_OTG_STEREO_STATUS, OTG_STEREO_CURRENT_EYE, mask_sh),\
+ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_EN, mask_sh),\
+ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_V_UPDATE_MODE, mask_sh),\
+ SF(OTG0_OTG_3D_STRUCTURE_CONTROL, OTG_3D_STRUCTURE_STEREO_SEL_OVR, mask_sh),\
+ SF(OTG0_OTG_V_TOTAL_MAX, OTG_V_TOTAL_MAX, mask_sh),\
+ SF(OTG0_OTG_V_TOTAL_MIN, OTG_V_TOTAL_MIN, mask_sh),\
+ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MIN_SEL, mask_sh),\
+ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_V_TOTAL_MAX_SEL, mask_sh),\
+ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_FORCE_LOCK_ON_EVENT, mask_sh),\
+ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_SET_V_TOTAL_MIN_MASK, mask_sh),\
+ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MIN_EN, mask_sh),\
+ SF(OTG0_OTG_V_TOTAL_CONTROL, OTG_VTOTAL_MID_REPLACING_MAX_EN, mask_sh),\
+ SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_CLEAR, mask_sh),\
+ SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_MODE, mask_sh),\
+ SF(OTG0_OTG_FORCE_COUNT_NOW_CNTL, OTG_FORCE_COUNT_NOW_OCCURRED, mask_sh),\
+ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_SELECT, mask_sh),\
+ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_SOURCE_PIPE_SELECT, mask_sh),\
+ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_RISING_EDGE_DETECT_CNTL, mask_sh),\
+ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, mask_sh),\
+ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_POLARITY_SELECT, mask_sh),\
+ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_FREQUENCY_SELECT, mask_sh),\
+ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_DELAY, mask_sh),\
+ SF(OTG0_OTG_TRIGA_CNTL, OTG_TRIGA_CLEAR, mask_sh),\
+ SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_EVENT_MASK, mask_sh),\
+ SF(OTG0_OTG_STATIC_SCREEN_CONTROL, OTG_STATIC_SCREEN_FRAME_COUNT, mask_sh),\
+ SF(OTG0_OTG_STATUS_FRAME_COUNT, OTG_FRAME_COUNT, mask_sh),\
+ SF(OTG0_OTG_STATUS, OTG_V_BLANK, mask_sh),\
+ SF(OTG0_OTG_STATUS, OTG_V_ACTIVE_DISP, mask_sh),\
+ SF(OTG0_OTG_STATUS_POSITION, OTG_HORZ_COUNT, mask_sh),\
+ SF(OTG0_OTG_STATUS_POSITION, OTG_VERT_COUNT, mask_sh),\
+ SF(OTG0_OTG_NOM_VERT_POSITION, OTG_VERT_COUNT_NOM, mask_sh),\
+ SF(OTG0_OTG_M_CONST_DTO0, OTG_M_CONST_DTO_PHASE, mask_sh),\
+ SF(OTG0_OTG_M_CONST_DTO1, OTG_M_CONST_DTO_MODULO, mask_sh),\
+ SF(OTG0_OTG_CLOCK_CONTROL, OTG_BUSY, mask_sh),\
+ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_EN, mask_sh),\
+ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_ON, mask_sh),\
+ SF(OTG0_OTG_CLOCK_CONTROL, OTG_CLOCK_GATE_DIS, mask_sh),\
+ SF(OTG0_OTG_VERTICAL_INTERRUPT0_CONTROL, OTG_VERTICAL_INTERRUPT0_INT_ENABLE, mask_sh),\
+ SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_START, mask_sh),\
+ SF(OTG0_OTG_VERTICAL_INTERRUPT0_POSITION, OTG_VERTICAL_INTERRUPT0_LINE_END, mask_sh),\
+ SF(OTG0_OTG_VERTICAL_INTERRUPT1_CONTROL, OTG_VERTICAL_INTERRUPT1_INT_ENABLE, mask_sh),\
+ SF(OTG0_OTG_VERTICAL_INTERRUPT1_POSITION, OTG_VERTICAL_INTERRUPT1_LINE_START, mask_sh),\
+ SF(OTG0_OTG_VERTICAL_INTERRUPT2_CONTROL, OTG_VERTICAL_INTERRUPT2_INT_ENABLE, mask_sh),\
+ SF(OTG0_OTG_VERTICAL_INTERRUPT2_POSITION, OTG_VERTICAL_INTERRUPT2_LINE_START, mask_sh),\
+ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_EN, mask_sh),\
+ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_ON, mask_sh),\
+ SF(ODM0_OPTC_INPUT_CLOCK_CONTROL, OPTC_INPUT_CLK_GATE_DIS, mask_sh),\
+ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_OCCURRED_STATUS, mask_sh),\
+ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_DOUBLE_BUFFER_PENDING, mask_sh),\
+ SF(ODM0_OPTC_INPUT_GLOBAL_CONTROL, OPTC_UNDERFLOW_CLEAR, mask_sh),\
+ SF(ODM0_OPTC_RSMU_UNDERFLOW, OPTC_RSMU_UNDERFLOW_OCCURRED_STATUS, mask_sh),\
+ SF(ODM0_OPTC_RSMU_UNDERFLOW, OPTC_RSMU_UNDERFLOW_CLEAR, mask_sh),\
+ SF(ODM0_OPTC_RSMU_UNDERFLOW, OPTC_RSMU_UNDERFLOW_INT_EN, mask_sh),\
+ SF(ODM0_OPTC_RSMU_UNDERFLOW, OPTC_RSMU_UNDERFLOW_INT_STATUS, mask_sh),\
+ SF(VTG0_CONTROL, VTG0_ENABLE, mask_sh),\
+ SF(VTG0_CONTROL, VTG0_FP2, mask_sh),\
+ SF(VTG0_CONTROL, VTG0_VCOUNT_INIT, mask_sh),\
+ SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_OCCURRED, mask_sh),\
+ SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_FORCE_VSYNC_NEXT_LINE_CLEAR, mask_sh),\
+ SF(OTG0_OTG_VERT_SYNC_CONTROL, OTG_AUTO_FORCE_VSYNC_MODE, mask_sh),\
+ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL0_EN, mask_sh),\
+ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL1_EN, mask_sh),\
+ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL2_EN, mask_sh),\
+ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_EN, mask_sh),\
+ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_FORCE_DELAY, mask_sh),\
+ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_CHECK_ALL_FIELDS, mask_sh),\
+ SF(OTG0_OTG_CRC_CNTL, OTG_CRC_CONT_EN, mask_sh),\
+ SF(OTG0_OTG_CRC_CNTL, OTG_CRC0_SELECT, mask_sh),\
+ SF(OTG0_OTG_CRC_CNTL, OTG_CRC_EN, mask_sh),\
+ SF(OTG0_OTG_CRC0_DATA_R, CRC0_R_CR, mask_sh),\
+ SF(OTG0_OTG_CRC0_DATA_G, CRC0_G_Y, mask_sh),\
+ SF(OTG0_OTG_CRC0_DATA_B, CRC0_B_CB, mask_sh),\
+ SF(OTG0_OTG_CRC1_DATA_R, CRC1_R_CR, mask_sh),\
+ SF(OTG0_OTG_CRC1_DATA_G, CRC1_G_Y, mask_sh),\
+ SF(OTG0_OTG_CRC1_DATA_B, CRC1_B_CB, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_START, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWA_X_CONTROL, OTG_CRC0_WINDOWA_X_END, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_START, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWA_Y_CONTROL, OTG_CRC0_WINDOWA_Y_END, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_START, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWB_X_CONTROL, OTG_CRC0_WINDOWB_X_END, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_START, mask_sh),\
+ SF(OTG0_OTG_CRC0_WINDOWB_Y_CONTROL, OTG_CRC0_WINDOWB_Y_END, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_X_CONTROL, OTG_CRC1_WINDOWA_X_END, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWA_Y_CONTROL, OTG_CRC1_WINDOWA_Y_END, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_X_CONTROL, OTG_CRC1_WINDOWB_X_END, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_START, mask_sh),\
+ SF(OTG0_OTG_CRC1_WINDOWB_Y_CONTROL, OTG_CRC1_WINDOWB_Y_END, mask_sh),\
+ SF(OTG0_OTG_TRIGA_MANUAL_TRIG, OTG_TRIGA_MANUAL_TRIG, mask_sh),\
+ SF(GSL_SOURCE_SELECT, GSL0_READY_SOURCE_SEL, mask_sh),\
+ SF(GSL_SOURCE_SELECT, GSL1_READY_SOURCE_SEL, mask_sh),\
+ SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\
+ SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh),\
+ SF(OTG0_OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, mask_sh),\
+ SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_START_X, mask_sh),\
+ SF(OTG0_OTG_GSL_WINDOW_X, OTG_GSL_WINDOW_END_X, mask_sh), \
+ SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_START_Y, mask_sh),\
+ SF(OTG0_OTG_GSL_WINDOW_Y, OTG_GSL_WINDOW_END_Y, mask_sh),\
+ SF(OTG0_OTG_VUPDATE_KEEPOUT, OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, mask_sh), \
+ SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, mask_sh), \
+ SF(OTG0_OTG_VUPDATE_KEEPOUT, MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, mask_sh), \
+ SF(OTG0_OTG_GSL_CONTROL, OTG_GSL_MASTER_MODE, mask_sh), \
+ SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \
+ SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\
+ SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\
+ SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG2_SRC_SEL, mask_sh),\
+ SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG3_SRC_SEL, mask_sh),\
+ SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\
+ SF(ODM0_OPTC_MEMORY_CONFIG, OPTC_MEM_SEL, mask_sh),\
+ SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, mask_sh),\
+ SF(ODM0_OPTC_DATA_FORMAT_CONTROL, OPTC_DSC_MODE, mask_sh),\
+ SF(ODM0_OPTC_BYTES_PER_PIXEL, OPTC_DSC_BYTES_PER_PIXEL, mask_sh),\
+ SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_DSC_SLICE_WIDTH, mask_sh),\
+ SF(ODM0_OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mask_sh),\
+ SF(ODM0_OPTC_WIDTH_CONTROL2, OPTC_SEGMENT_WIDTH_LAST, mask_sh),\
+ SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_START_X, mask_sh),\
+ SF(OTG0_OTG_DRR_TRIGGER_WINDOW, OTG_DRR_TRIGGER_WINDOW_END_X, mask_sh),\
+ SF(OTG0_OTG_DRR_V_TOTAL_CHANGE, OTG_DRR_V_TOTAL_CHANGE_LIMIT, mask_sh),\
+ SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, mask_sh),\
+ SF(OTG0_OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE_MANUAL, mask_sh),\
+ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_MODE, mask_sh),\
+ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_DRR_TIMING_DBUF_UPDATE_PENDING, mask_sh),\
+ SF(OTG0_OTG_DRR_CONTROL, OTG_V_TOTAL_LAST_USED_BY_DRR, mask_sh),\
+ SF(OTG0_OTG_PSTATE_REGISTER, OTG_PSTATE_KEEPOUT_START, mask_sh),\
+ SF(OTG0_OTG_PSTATE_REGISTER, OTG_PSTATE_EXTEND, mask_sh),\
+ SF(OTG0_OTG_PSTATE_REGISTER, OTG_UNBLANK, mask_sh),\
+ SF(OTG0_OTG_PSTATE_REGISTER, OTG_PSTATE_ALLOW_WIDTH_MIN, mask_sh),\
+ SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_FLIP_PENDING, mask_sh),\
+ SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_DC_REG_UPDATE_PENDING, mask_sh),\
+ SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_CURSOR_UPDATE_PENDING, mask_sh),\
+ SF(OTG0_OTG_PIPE_UPDATE_STATUS, OTG_VUPDATE_KEEPOUT_STATUS, mask_sh),\
+ SF(OTG0_OTG_PWA_FRAME_SYNC_CONTROL, OTG_PWA_FRAME_SYNC_EN, mask_sh),\
+ SF(OTG0_OTG_PWA_FRAME_SYNC_CONTROL, OTG_PWA_FRAME_SYNC_VCOUNT_MODE, mask_sh),\
+ SF(OTG0_OTG_PWA_FRAME_SYNC_CONTROL, OTG_PWA_FRAME_SYNC_LINE, mask_sh),\
+ SF(OTG0_INTERRUPT_DEST, OTG0_IHC_OTG_VERTICAL_INTERRUPT2_DEST, mask_sh),\
+ SF(OPTC_CLOCK_CONTROL, OPTC_FGCG_REP_DIS, mask_sh)
+
+void dcn42_timing_generator_init(struct optc *optc1);
+void optc42_enable_pwa(struct timing_generator *optc, struct otc_pwa_frame_sync *pwa_sync_param);
+void optc42_disable_pwa(struct timing_generator *optc);
+void optc42_tg_init(struct timing_generator *optc);
+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);
+#endif /* __DC_OPTC_DCN42_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/pg/Makefile b/drivers/gpu/drm/amd/display/dc/pg/Makefile
index ec11d3157a57..56f610cc8406 100644
--- a/drivers/gpu/drm/amd/display/dc/pg/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/pg/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright 2020 Advanced Micro Devices, Inc.
+# Copyright 2020, 2026 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -32,4 +32,12 @@ PG_DCN35 = dcn35_pg_cntl.o
AMD_DAL_PG_DCN35 = $(addprefix $(AMDDALPATH)/dc/pg/dcn35/,$(PG_DCN35))
AMD_DISPLAY_FILES += $(AMD_DAL_PG_DCN35)
+###############################################################################
+# DCN42
+###############################################################################
+PG_DCN42 = dcn42_pg_cntl.o
+
+AMD_DAL_PG_DCN42 = $(addprefix $(AMDDALPATH)/dc/pg/dcn42/,$(PG_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_PG_DCN42)
endif
diff --git a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c
new file mode 100644
index 000000000000..96290538a889
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.c
@@ -0,0 +1,649 @@
+// SPDX-License-Identifier: MIT
+
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "reg_helper.h"
+#include "core_types.h"
+#include "dcn42_pg_cntl.h"
+#include "dccg.h"
+
+#define TO_DCN_PG_CNTL(pg_cntl)\
+ container_of(pg_cntl, struct dcn_pg_cntl, base)
+
+#define REG(reg) \
+ (pg_cntl_dcn->regs->reg)
+
+#undef FN
+#define FN(reg_name, field_name) \
+ pg_cntl_dcn->pg_cntl_shift->field_name, pg_cntl_dcn->pg_cntl_mask->field_name
+
+#define CTX \
+ pg_cntl_dcn->base.ctx
+#define DC_LOGGER \
+ pg_cntl->ctx->logger
+
+static bool pg_cntl42_dsc_pg_status(struct pg_cntl *pg_cntl, unsigned int dsc_inst)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t pwr_status = 0;
+
+ if (pg_cntl->ctx->dc->debug.ignore_pg)
+ return true;
+
+ switch (dsc_inst) {
+ case 0: /* DSC0 */
+ REG_GET(DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ case 1: /* DSC1 */
+ REG_GET(DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ case 2: /* DSC2 */
+ REG_GET(DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ case 3: /* DSC3 */
+ REG_GET(DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ break;
+ }
+
+ return pwr_status == 0;
+}
+
+void pg_cntl42_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bool power_on)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t power_gate = power_on ? 0 : 1;
+ uint32_t pwr_status = power_on ? 0 : 2;
+ uint32_t org_ip_request_cntl = 0;
+ bool block_enabled;
+
+ /*need to enable dscclk regardless DSC_PG*/
+ if (pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc && power_on)
+ pg_cntl->ctx->dc->res_pool->dccg->funcs->enable_dsc(
+ pg_cntl->ctx->dc->res_pool->dccg, dsc_inst);
+
+ if (pg_cntl->ctx->dc->debug.ignore_pg ||
+ pg_cntl->ctx->dc->debug.disable_dsc_power_gate ||
+ pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ block_enabled = pg_cntl42_dsc_pg_status(pg_cntl, dsc_inst);
+ if (power_on) {
+ if (block_enabled)
+ return;
+ } else {
+ if (!block_enabled)
+ return;
+ }
+
+ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+ if (org_ip_request_cntl == 0)
+ REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+ if (power_on) {
+ if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+ pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, false);
+ }
+ switch (dsc_inst) {
+ case 0: /* DSC0 */
+ REG_UPDATE(DOMAIN16_PG_CONFIG,
+ DOMAIN_POWER_GATE, power_gate);
+
+ REG_WAIT(DOMAIN16_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+ 1, 1000);
+ break;
+ case 1: /* DSC1 */
+ REG_UPDATE(DOMAIN17_PG_CONFIG,
+ DOMAIN_POWER_GATE, power_gate);
+
+ REG_WAIT(DOMAIN17_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+ 1, 1000);
+ break;
+ case 2: /* DSC2 */
+ REG_UPDATE(DOMAIN18_PG_CONFIG,
+ DOMAIN_POWER_GATE, power_gate);
+
+ REG_WAIT(DOMAIN18_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+ 1, 1000);
+ break;
+ case 3: /* DSC3 */
+ REG_UPDATE(DOMAIN19_PG_CONFIG,
+ DOMAIN_POWER_GATE, power_gate);
+
+ REG_WAIT(DOMAIN19_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, pwr_status,
+ 1, 1000);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ break;
+ }
+
+ if (power_on) {
+ if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+ pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, true);
+ }
+
+ if (dsc_inst < MAX_PIPES)
+ pg_cntl->pg_pipe_res_enable[PG_DSC][dsc_inst] = power_on;
+
+ if (pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc && !power_on) {
+ /*this is to disable dscclk*/
+ pg_cntl->ctx->dc->res_pool->dccg->funcs->disable_dsc(
+ pg_cntl->ctx->dc->res_pool->dccg, dsc_inst);
+ }
+}
+
+static bool pg_cntl42_hubp_dpp_pg_status(struct pg_cntl *pg_cntl, unsigned int hubp_dpp_inst)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t pwr_status = 0;
+
+ switch (hubp_dpp_inst) {
+ case 0:
+ /* DPP0 & HUBP0 */
+ REG_GET(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ case 1:
+ /* DPP1 & HUBP1 */
+ REG_GET(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ case 2:
+ /* DPP2 & HUBP2 */
+ REG_GET(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ case 3:
+ /* DPP3 & HUBP3 */
+ REG_GET(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ break;
+ }
+
+ return pwr_status == 0;
+}
+
+void pg_cntl42_hubp_dpp_pg_control(struct pg_cntl *pg_cntl, unsigned int hubp_dpp_inst, bool power_on)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t power_gate = power_on ? 0 : 1;
+ uint32_t pwr_status = power_on ? 0 : 2;
+ uint32_t org_ip_request_cntl;
+ bool block_enabled;
+ bool skip_pg = pg_cntl->ctx->dc->debug.ignore_pg ||
+ pg_cntl->ctx->dc->debug.disable_hubp_power_gate ||
+ pg_cntl->ctx->dc->debug.disable_dpp_power_gate ||
+ pg_cntl->ctx->dc->idle_optimizations_allowed;
+
+ if (skip_pg && !power_on)
+ return;
+
+ block_enabled = pg_cntl42_hubp_dpp_pg_status(pg_cntl, hubp_dpp_inst);
+ if (power_on) {
+ if (block_enabled)
+ return;
+ } else {
+ if (!block_enabled)
+ return;
+ }
+
+ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+ if (org_ip_request_cntl == 0)
+ REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+ if (power_on) {
+ if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+ pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, false);
+ }
+
+ switch (hubp_dpp_inst) {
+ case 0:
+ /* DPP0 & HUBP0 */
+ REG_UPDATE(DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+ break;
+ case 1:
+ /* DPP1 & HUBP1 */
+ REG_UPDATE(DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+ break;
+ case 2:
+ /* DPP2 & HUBP2 */
+ REG_UPDATE(DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+ break;
+ case 3:
+ /* DPP3 & HUBP3 */
+ REG_UPDATE(DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+ break;
+ default:
+ BREAK_TO_DEBUGGER();
+ break;
+ }
+
+ if (power_on) {
+ if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+ pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, true);
+ }
+ DC_LOG_DEBUG("HUBP DPP instance %d, power %s", hubp_dpp_inst,
+ power_on ? "ON" : "OFF");
+
+ if (hubp_dpp_inst < MAX_PIPES) {
+ pg_cntl->pg_pipe_res_enable[PG_HUBP][hubp_dpp_inst] = power_on;
+ pg_cntl->pg_pipe_res_enable[PG_DPP][hubp_dpp_inst] = power_on;
+ }
+}
+
+static bool pg_cntl42_hpo_pg_status(struct pg_cntl *pg_cntl)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t pwr_status = 0;
+
+ REG_GET(DOMAIN25_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+ return pwr_status == 0;
+}
+
+void pg_cntl42_hpo_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t power_gate = power_on ? 0 : 1;
+ uint32_t pwr_status = power_on ? 0 : 2;
+ uint32_t org_ip_request_cntl;
+ uint32_t power_forceon;
+ bool block_enabled;
+
+ if (pg_cntl->ctx->dc->debug.ignore_pg ||
+ pg_cntl->ctx->dc->debug.disable_hpo_power_gate ||
+ pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ block_enabled = pg_cntl42_hpo_pg_status(pg_cntl);
+ if (power_on) {
+ if (block_enabled)
+ return;
+ } else {
+ if (!block_enabled)
+ return;
+ }
+
+ REG_GET(DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, &power_forceon);
+ if (power_forceon)
+ return;
+
+ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+ if (org_ip_request_cntl == 0)
+ REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+ if (power_on) {
+ if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+ pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, false);
+ }
+ REG_UPDATE(DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+
+ if (power_on) {
+ if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+ pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, true);
+ }
+ pg_cntl->pg_res_enable[PG_HPO] = power_on;
+}
+
+static bool pg_cntl42_io_clk_status(struct pg_cntl *pg_cntl)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t pwr_status = 0;
+
+ REG_GET(DOMAIN22_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+ return pwr_status == 0;
+}
+
+void pg_cntl42_io_clk_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t power_gate = power_on ? 0 : 1;
+ uint32_t pwr_status = power_on ? 0 : 2;
+ uint32_t org_ip_request_cntl;
+ uint32_t power_forceon;
+ bool block_enabled;
+
+ if (pg_cntl->ctx->dc->debug.ignore_pg ||
+ pg_cntl->ctx->dc->idle_optimizations_allowed ||
+ pg_cntl->ctx->dc->debug.disable_io_clk_power_gate)
+ return;
+
+ block_enabled = pg_cntl42_io_clk_status(pg_cntl);
+ if (power_on) {
+ if (block_enabled)
+ return;
+ } else {
+ if (!block_enabled)
+ return;
+ }
+
+ REG_GET(DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, &power_forceon);
+ if (power_forceon)
+ return;
+
+ if (!power_on) {
+ if (!pg_cntl->pg_res_enable[PG_DCCG] || !pg_cntl->pg_res_enable[PG_DCIO] || !pg_cntl->pg_res_enable[PG_DCOH])
+ return;
+ }
+ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+ if (org_ip_request_cntl == 0)
+ REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+ /* DCCG, DCOH, DCIO */
+ REG_UPDATE(DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+
+ pg_cntl->pg_res_enable[PG_DCCG] = power_on;
+ pg_cntl->pg_res_enable[PG_DCOH] = power_on;
+ pg_cntl->pg_res_enable[PG_DCIO] = power_on;
+}
+
+static bool pg_cntl42_plane_otg_status(struct pg_cntl *pg_cntl)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t pwr_status = 0;
+
+ REG_GET(DOMAIN24_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+ return pwr_status == 0;
+}
+
+void pg_cntl42_mpcc_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int mpcc_inst, bool power_on)
+{
+ if (pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ if (mpcc_inst < MAX_PIPES)
+ pg_cntl->pg_pipe_res_enable[PG_MPCC][mpcc_inst] = power_on;
+}
+
+void pg_cntl42_opp_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int opp_inst, bool power_on)
+{
+ if (pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ if (opp_inst < MAX_PIPES)
+ pg_cntl->pg_pipe_res_enable[PG_OPP][opp_inst] = power_on;
+}
+
+void pg_cntl42_optc_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int optc_inst, bool power_on)
+{
+ // Defer the ONO domain power up/down to plane_otg_pg_control
+ if (pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ if (optc_inst < MAX_PIPES)
+ pg_cntl->pg_pipe_res_enable[PG_OPTC][optc_inst] = power_on;
+}
+static bool pg_cntl42_mem_status(struct pg_cntl *pg_cntl)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t pwr_status = 0;
+
+ REG_GET(DOMAIN23_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+ return pwr_status == 0;
+}
+
+void pg_cntl42_mem_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t power_gate = power_on ? 0 : 1;
+ uint32_t pwr_status = power_on ? 0 : 2;
+ uint32_t org_ip_request_cntl;
+ uint32_t power_forceon;
+ bool block_enabled;
+
+ if (pg_cntl->ctx->dc->debug.ignore_pg ||
+ pg_cntl->ctx->dc->idle_optimizations_allowed ||
+ pg_cntl->ctx->dc->debug.disable_mem_power_gate)
+ return;
+
+ block_enabled = pg_cntl42_mem_status(pg_cntl);
+ if (power_on) {
+ if (block_enabled)
+ return;
+ } else {
+ if (!block_enabled)
+ return;
+ }
+
+ REG_GET(DOMAIN23_PG_CONFIG, DOMAIN_POWER_FORCEON, &power_forceon);
+ if (power_forceon)
+ return;
+
+ if (!power_on) {
+ if (!pg_cntl->pg_res_enable[PG_DCHUBBUB] || !pg_cntl->pg_res_enable[PG_DCHVM])
+ return;
+ }
+ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+ if (org_ip_request_cntl == 0)
+ REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+ /* DCHUBBUB, DCHUBBUBMEMn, DCHVM */
+ REG_UPDATE(DOMAIN23_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN23_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+
+ pg_cntl->pg_res_enable[PG_DCHUBBUB] = power_on;
+ pg_cntl->pg_res_enable[PG_DCHVM] = power_on;
+}
+static bool pg_cntl42_dio_pg_status(struct pg_cntl *pg_cntl)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t pwr_status = 0;
+
+ REG_GET(DOMAIN26_PG_STATUS,
+ DOMAIN_PGFSM_PWR_STATUS, &pwr_status);
+
+ return pwr_status == 0;
+}
+
+void pg_cntl42_dio_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t power_gate = power_on ? 0 : 1;
+ uint32_t pwr_status = power_on ? 0 : 2;
+ uint32_t org_ip_request_cntl;
+ bool block_enabled;
+
+ if (pg_cntl->ctx->dc->debug.ignore_pg ||
+ pg_cntl->ctx->dc->idle_optimizations_allowed ||
+ pg_cntl->ctx->dc->debug.disable_dio_power_gate)
+ return;
+
+ block_enabled = pg_cntl42_dio_pg_status(pg_cntl);
+ if (power_on) {
+ if (block_enabled)
+ return;
+ } else {
+ if (!block_enabled)
+ return;
+ }
+
+ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+ if (org_ip_request_cntl == 0)
+ REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+ if (power_on) {
+ if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+ pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, false);
+ }
+ /* DIO */
+ REG_UPDATE(DOMAIN26_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN26_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+
+ if (power_on) {
+ if (pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg)
+ pg_cntl->ctx->dc->res_pool->dccg->funcs->dccg_enable_global_fgcg(pg_cntl->ctx->dc->res_pool->dccg, true);
+ }
+ pg_cntl->pg_res_enable[PG_DIO] = power_on;
+
+}
+
+void pg_cntl42_plane_otg_pg_control(struct pg_cntl *pg_cntl, bool power_on)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(pg_cntl);
+ uint32_t power_gate = power_on ? 0 : 1;
+ uint32_t pwr_status = power_on ? 0 : 2;
+ uint32_t org_ip_request_cntl;
+ int i;
+ bool block_enabled;
+ bool all_mpcc_disabled = true, all_opp_disabled = true;
+ bool all_optc_disabled = true, all_stream_disabled = true;
+
+ if (pg_cntl->ctx->dc->debug.ignore_pg ||
+ pg_cntl->ctx->dc->debug.disable_optc_power_gate ||
+ pg_cntl->ctx->dc->idle_optimizations_allowed)
+ return;
+
+ block_enabled = pg_cntl42_plane_otg_status(pg_cntl);
+ if (power_on) {
+ if (block_enabled)
+ return;
+ } else {
+ if (!block_enabled)
+ return;
+ }
+
+ for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx = &pg_cntl->ctx->dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (pipe_ctx) {
+ if (pipe_ctx->stream)
+ all_stream_disabled = false;
+ }
+
+ if (pg_cntl->pg_pipe_res_enable[PG_MPCC][i])
+ all_mpcc_disabled = false;
+
+ if (pg_cntl->pg_pipe_res_enable[PG_OPP][i])
+ all_opp_disabled = false;
+
+ if (pg_cntl->pg_pipe_res_enable[PG_OPTC][i])
+ all_optc_disabled = false;
+ }
+
+ if (!power_on) {
+ if (!all_mpcc_disabled || !all_opp_disabled || !all_optc_disabled
+ || !all_stream_disabled)
+ return;
+ }
+
+ REG_GET(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, &org_ip_request_cntl);
+ if (org_ip_request_cntl == 0)
+ REG_SET(DC_IP_REQUEST_CNTL, 0, IP_REQUEST_EN, 1);
+
+ /* MPC, OPP, OPTC, DWB */
+ REG_UPDATE(DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, power_gate);
+ REG_WAIT(DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, pwr_status, 1, 1000);
+
+ for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) {
+ pg_cntl->pg_pipe_res_enable[PG_MPCC][i] = power_on;
+ pg_cntl->pg_pipe_res_enable[PG_OPP][i] = power_on;
+ pg_cntl->pg_pipe_res_enable[PG_OPTC][i] = power_on;
+ }
+}
+
+
+void pg_cntl42_init_pg_status(struct pg_cntl *pg_cntl)
+{
+ int i = 0;
+ bool block_enabled;
+
+ pg_cntl->pg_res_enable[PG_HPO] = pg_cntl42_hpo_pg_status(pg_cntl);
+
+ block_enabled = pg_cntl42_io_clk_status(pg_cntl);
+ pg_cntl->pg_res_enable[PG_DCCG] = block_enabled;
+ pg_cntl->pg_res_enable[PG_DCIO] = block_enabled;
+ pg_cntl->pg_res_enable[PG_DCOH] = block_enabled;
+
+ block_enabled = pg_cntl42_dio_pg_status(pg_cntl);
+ pg_cntl->pg_res_enable[PG_DIO] = block_enabled;
+
+ block_enabled = pg_cntl42_mem_status(pg_cntl);
+ pg_cntl->pg_res_enable[PG_DCHUBBUB] = block_enabled;
+ pg_cntl->pg_res_enable[PG_DCHVM] = block_enabled;
+
+ for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) {
+ block_enabled = pg_cntl42_hubp_dpp_pg_status(pg_cntl, i);
+ pg_cntl->pg_pipe_res_enable[PG_HUBP][i] = block_enabled;
+ pg_cntl->pg_pipe_res_enable[PG_DPP][i] = block_enabled;
+
+ block_enabled = pg_cntl42_dsc_pg_status(pg_cntl, i);
+ pg_cntl->pg_pipe_res_enable[PG_DSC][i] = block_enabled;
+ }
+
+ block_enabled = pg_cntl42_plane_otg_status(pg_cntl);
+ for (i = 0; i < pg_cntl->ctx->dc->res_pool->pipe_count; i++) {
+ pg_cntl->pg_pipe_res_enable[PG_MPCC][i] = block_enabled;
+ pg_cntl->pg_pipe_res_enable[PG_OPP][i] = block_enabled;
+ pg_cntl->pg_pipe_res_enable[PG_OPTC][i] = block_enabled;
+ }
+}
+
+static const struct pg_cntl_funcs pg_cntl42_funcs = {
+ .init_pg_status = pg_cntl42_init_pg_status,
+ .dsc_pg_control = pg_cntl42_dsc_pg_control,
+ .hubp_dpp_pg_control = pg_cntl42_hubp_dpp_pg_control,
+ .hpo_pg_control = pg_cntl42_hpo_pg_control,
+ .io_clk_pg_control = pg_cntl42_io_clk_pg_control,
+ .plane_otg_pg_control = pg_cntl42_plane_otg_pg_control,
+ .mpcc_pg_control = pg_cntl42_mpcc_pg_control,
+ .opp_pg_control = pg_cntl42_opp_pg_control,
+ .optc_pg_control = pg_cntl42_optc_pg_control,
+ .mem_pg_control = pg_cntl42_mem_pg_control,
+ .dio_pg_control = pg_cntl42_dio_pg_control
+};
+
+struct pg_cntl *pg_cntl42_create(
+ struct dc_context *ctx,
+ const struct pg_cntl_registers *regs,
+ const struct pg_cntl_shift *pg_cntl_shift,
+ const struct pg_cntl_mask *pg_cntl_mask)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = kzalloc(sizeof(*pg_cntl_dcn), GFP_KERNEL);
+ struct pg_cntl *base;
+
+ if (pg_cntl_dcn == NULL) {
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+
+ base = &pg_cntl_dcn->base;
+ base->ctx = ctx;
+ base->funcs = &pg_cntl42_funcs;
+
+ pg_cntl_dcn->regs = regs;
+ pg_cntl_dcn->pg_cntl_shift = pg_cntl_shift;
+ pg_cntl_dcn->pg_cntl_mask = pg_cntl_mask;
+
+ memset(base->pg_pipe_res_enable, 0, PG_HW_PIPE_RESOURCES_NUM_ELEMENT * MAX_PIPES * sizeof(bool));
+ memset(base->pg_res_enable, 0, PG_HW_RESOURCES_NUM_ELEMENT * sizeof(bool));
+
+ return &pg_cntl_dcn->base;
+}
+
+void dcn42_pg_cntl_destroy(struct pg_cntl **pg_cntl)
+{
+ struct dcn_pg_cntl *pg_cntl_dcn = TO_DCN_PG_CNTL(*pg_cntl);
+
+ kfree(pg_cntl_dcn);
+ *pg_cntl = NULL;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h
new file mode 100644
index 000000000000..a0aa14a796f4
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/pg/dcn42/dcn42_pg_cntl.h
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: MIT */
+
+/* Copyright 2026 Advanced Micro Devices, Inc.*/
+
+#ifndef __DCN42_PG_CNTL_H__
+#define __DCN42_PG_CNTL_H__
+
+#include "pg_cntl.h"
+
+#define PG_CNTL_REG_LIST_DCN42()\
+ SR(DOMAIN0_PG_CONFIG), \
+ SR(DOMAIN1_PG_CONFIG), \
+ SR(DOMAIN2_PG_CONFIG), \
+ SR(DOMAIN3_PG_CONFIG), \
+ SR(DOMAIN16_PG_CONFIG), \
+ SR(DOMAIN17_PG_CONFIG), \
+ SR(DOMAIN18_PG_CONFIG), \
+ SR(DOMAIN19_PG_CONFIG), \
+ SR(DOMAIN22_PG_CONFIG), \
+ SR(DOMAIN23_PG_CONFIG), \
+ SR(DOMAIN24_PG_CONFIG), \
+ SR(DOMAIN25_PG_CONFIG), \
+ SR(DOMAIN26_PG_CONFIG), \
+ SR(DOMAIN0_PG_STATUS), \
+ SR(DOMAIN1_PG_STATUS), \
+ SR(DOMAIN2_PG_STATUS), \
+ SR(DOMAIN3_PG_STATUS), \
+ SR(DOMAIN16_PG_STATUS), \
+ SR(DOMAIN17_PG_STATUS), \
+ SR(DOMAIN18_PG_STATUS), \
+ SR(DOMAIN19_PG_STATUS), \
+ SR(DOMAIN22_PG_STATUS), \
+ SR(DOMAIN23_PG_STATUS), \
+ SR(DOMAIN24_PG_STATUS), \
+ SR(DOMAIN25_PG_STATUS), \
+ SR(DOMAIN26_PG_STATUS), \
+ SR(DC_IP_REQUEST_CNTL)
+
+#define PG_CNTL_SF(reg_name, field_name, post_fix)\
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
+#define PG_CNTL_MASK_SH_LIST_DCN42(mask_sh) \
+ PG_CNTL_SF(DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN23_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN23_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN24_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN26_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ PG_CNTL_SF(DOMAIN26_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN0_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN1_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN2_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN3_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN16_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN17_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN18_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN19_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN22_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN23_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN23_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN24_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN25_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DOMAIN26_PG_STATUS, DOMAIN_DESIRED_PWR_STATE, mask_sh), \
+ PG_CNTL_SF(DOMAIN26_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ PG_CNTL_SF(DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh)
+
+struct pg_cntl_shift {
+ uint8_t IP_REQUEST_EN;
+ uint8_t DOMAIN_POWER_FORCEON;
+ uint8_t DOMAIN_POWER_GATE;
+ uint8_t DOMAIN_DESIRED_PWR_STATE;
+ uint8_t DOMAIN_PGFSM_PWR_STATUS;
+};
+struct pg_cntl_mask {
+ uint32_t IP_REQUEST_EN;
+ uint32_t DOMAIN_POWER_FORCEON;
+ uint32_t DOMAIN_POWER_GATE;
+ uint32_t DOMAIN_DESIRED_PWR_STATE;
+ uint32_t DOMAIN_PGFSM_PWR_STATUS;
+};
+
+struct pg_cntl_registers {
+ uint32_t LONO_STATE;
+ uint32_t DC_IP_REQUEST_CNTL;
+ uint32_t DOMAIN0_PG_CONFIG;
+ uint32_t DOMAIN1_PG_CONFIG;
+ uint32_t DOMAIN2_PG_CONFIG;
+ uint32_t DOMAIN3_PG_CONFIG;
+ uint32_t DOMAIN16_PG_CONFIG;
+ uint32_t DOMAIN17_PG_CONFIG;
+ uint32_t DOMAIN18_PG_CONFIG;
+ uint32_t DOMAIN19_PG_CONFIG;
+ uint32_t DOMAIN22_PG_CONFIG;
+ uint32_t DOMAIN23_PG_CONFIG;
+ uint32_t DOMAIN24_PG_CONFIG;
+ uint32_t DOMAIN25_PG_CONFIG;
+ uint32_t DOMAIN26_PG_CONFIG;
+ uint32_t DOMAIN0_PG_STATUS;
+ uint32_t DOMAIN1_PG_STATUS;
+ uint32_t DOMAIN2_PG_STATUS;
+ uint32_t DOMAIN3_PG_STATUS;
+ uint32_t DOMAIN16_PG_STATUS;
+ uint32_t DOMAIN17_PG_STATUS;
+ uint32_t DOMAIN18_PG_STATUS;
+ uint32_t DOMAIN19_PG_STATUS;
+ uint32_t DOMAIN22_PG_STATUS;
+ uint32_t DOMAIN23_PG_STATUS;
+ uint32_t DOMAIN24_PG_STATUS;
+ uint32_t DOMAIN25_PG_STATUS;
+ uint32_t DOMAIN26_PG_STATUS;
+};
+
+struct dcn_pg_cntl {
+ struct pg_cntl base;
+ const struct pg_cntl_registers *regs;
+ const struct pg_cntl_shift *pg_cntl_shift;
+ const struct pg_cntl_mask *pg_cntl_mask;
+};
+
+void pg_cntl42_dsc_pg_control(struct pg_cntl *pg_cntl, unsigned int dsc_inst, bool power_on);
+void pg_cntl42_hubp_dpp_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int hubp_dpp_inst, bool power_on);
+void pg_cntl42_hpo_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void pg_cntl42_io_clk_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void pg_cntl42_plane_otg_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void pg_cntl42_mpcc_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int mpcc_inst, bool power_on);
+void pg_cntl42_opp_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int opp_inst, bool power_on);
+void pg_cntl42_optc_pg_control(struct pg_cntl *pg_cntl,
+ unsigned int optc_inst, bool power_on);
+void pg_cntl42_mem_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void pg_cntl42_dio_pg_control(struct pg_cntl *pg_cntl, bool power_on);
+void dcn42_pg_cntl_destroy(struct pg_cntl **pg_cntl);
+void pg_cntl42_init_pg_status(struct pg_cntl *pg_cntl);
+
+struct pg_cntl *pg_cntl42_create(
+ struct dc_context *ctx,
+ const struct pg_cntl_registers *regs,
+ const struct pg_cntl_shift *pg_cntl_shift,
+ const struct pg_cntl_mask *pg_cntl_mask);
+
+void dcn_pg_cntl_destroy(struct pg_cntl **pg_cntl);
+
+#endif /* DCN42_PG_CNTL */
diff --git a/drivers/gpu/drm/amd/display/dc/resource/Makefile b/drivers/gpu/drm/amd/display/dc/resource/Makefile
index 5b42da8b79c2..1a17a885fe84 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/resource/Makefile
@@ -222,4 +222,22 @@ AMD_DAL_RESOURCE_DCN401 = $(addprefix $(AMDDALPATH)/dc/resource/dcn401/,$(RESOUR
AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN401)
+###############################################################################
+# DCN42
+###############################################################################
+RESOURCE_DCN42 = dcn42_resource.o dcn42_resource_fpu.o
+
+AMD_DAL_RESOURCE_DCN42 = $(addprefix $(AMDDALPATH)/dc/resource/dcn42/,$(RESOURCE_DCN42))
+
+AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN42)
+
+# FPU Compile Flags for FPU files
+resource_ccflags := $(CC_FLAGS_FPU)
+resource_rcflags := $(CC_FLAGS_NO_FPU)
+
+CFLAGS_$(AMDDALPATH)/dc/resource/dcn42/dcn42_resource_fpu.o := $(resource_ccflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/resource/dcn42/dcn42_resource_fpu.o := $(resource_rcflags)
+
+###############################################################################
endif
+
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
index fdcf8db6be50..caafebe92129 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
@@ -632,6 +632,7 @@ static struct link_encoder *dce100_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dce110_link_encoder *enc110 =
kzalloc_obj(struct dce110_link_encoder);
int link_regs_id;
@@ -849,6 +850,7 @@ static enum dc_status build_mapped_resource(
struct dc_state *context,
struct dc_stream_state *stream)
{
+ (void)dc;
struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
if (!pipe_ctx)
@@ -866,6 +868,7 @@ enum dc_status dce100_validate_bandwidth(
struct dc_state *context,
enum dc_validate_mode validate_mode)
{
+ (void)validate_mode;
int i;
bool at_least_one_pipe = false;
struct dc_stream_state *stream = NULL;
@@ -926,6 +929,7 @@ enum dc_status dce100_validate_global(
struct dc *dc,
struct dc_state *context)
{
+ (void)dc;
if (!dce100_validate_surface_sets(context))
return DC_FAIL_SURFACE_VALIDATE;
@@ -961,6 +965,7 @@ static void dce100_destroy_resource_pool(struct resource_pool **pool)
enum dc_status dce100_validate_plane(const struct dc_plane_state *plane_state, struct dc_caps *caps)
{
+ (void)caps;
if (plane_state->format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
return DC_OK;
@@ -1039,7 +1044,7 @@ static bool dce100_resource_construct(
pool->base.res_cap = &res_cap;
pool->base.funcs = &dce100_res_pool_funcs;
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
bp = ctx->dc_bios;
@@ -1111,7 +1116,7 @@ static bool dce100_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = res_cap.num_timing_generator;
pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 200;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c
index ab71f645c90e..f83acfe7a15e 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce110/dce110_resource.c
@@ -667,6 +667,7 @@ static struct link_encoder *dce110_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dce110_link_encoder *enc110 =
kzalloc_obj(struct dce110_link_encoder);
int link_regs_id;
@@ -971,6 +972,7 @@ static enum dc_status dce110_validate_bandwidth(
struct dc_state *context,
enum dc_validate_mode validate_mode)
{
+ (void)validate_mode;
bool result = false;
DC_LOG_BANDWIDTH_CALCS(
@@ -1043,6 +1045,7 @@ static enum dc_status dce110_validate_bandwidth(
static enum dc_status dce110_validate_plane(const struct dc_plane_state *plane_state,
struct dc_caps *caps)
{
+ (void)caps;
if (((plane_state->dst_rect.width * 2) < plane_state->src_rect.width) ||
((plane_state->dst_rect.height * 2) < plane_state->src_rect.height))
return DC_FAIL_SURFACE_VALIDATE;
@@ -1099,6 +1102,7 @@ static enum dc_status dce110_validate_global(
struct dc *dc,
struct dc_state *context)
{
+ (void)dc;
if (!dce110_validate_surface_sets(context))
return DC_FAIL_SURFACE_VALIDATE;
@@ -1130,6 +1134,7 @@ static struct pipe_ctx *dce110_acquire_underlay(
const struct resource_pool *pool,
const struct pipe_ctx *opp_head_pipe)
{
+ (void)cur_ctx;
struct dc_stream_state *stream = opp_head_pipe->stream;
struct dc *dc = stream->ctx->dc;
struct dce_hwseq *hws = dc->hwseq;
@@ -1354,6 +1359,7 @@ static bool dce110_resource_construct(
struct dce110_resource_pool *pool,
struct hw_asic_id asic_id)
{
+ (void)asic_id;
unsigned int i;
struct dc_context *ctx = dc->ctx;
struct dc_bios *bp;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c
index b7051bfd4326..458b14e4cb97 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce112/dce112_resource.c
@@ -628,6 +628,7 @@ static struct link_encoder *dce112_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dce110_link_encoder *enc110 =
kzalloc_obj(struct dce110_link_encoder);
int link_regs_id;
@@ -852,6 +853,7 @@ static struct clock_source *find_matching_pll(
const struct resource_pool *pool,
const struct dc_stream_state *const stream)
{
+ (void)res_ctx;
switch (stream->link->link_enc->transmitter) {
case TRANSMITTER_UNIPHY_A:
return pool->clock_sources[DCE112_CLK_SRC_PLL0];
@@ -875,6 +877,7 @@ static enum dc_status build_mapped_resource(
struct dc_state *context,
struct dc_stream_state *stream)
{
+ (void)dc;
struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
if (!pipe_ctx)
@@ -892,6 +895,7 @@ enum dc_status dce112_validate_bandwidth(
struct dc_state *context,
enum dc_validate_mode validate_mode)
{
+ (void)validate_mode;
bool result = false;
DC_LOG_BANDWIDTH_CALCS(
@@ -1037,6 +1041,7 @@ static enum dc_status dce112_validate_global(
struct dc *dc,
struct dc_state *context)
{
+ (void)dc;
if (!dce112_validate_surface_sets(context))
return DC_FAIL_SURFACE_VALIDATE;
@@ -1240,7 +1245,7 @@ static bool dce112_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 200;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c
index 7ee70f7b3aa7..56bbf9dc1691 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce120/dce120_resource.c
@@ -712,6 +712,7 @@ static struct link_encoder *dce120_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dce110_link_encoder *enc110 =
kzalloc_obj(struct dce110_link_encoder);
int link_regs_id;
@@ -1081,7 +1082,7 @@ static bool dce120_resource_construct(
/* TODO: Fill more data from GreenlandAsicCapability.cpp */
pool->base.pipe_count = res_cap.num_timing_generator;
pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator;
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
dc->caps.max_downscale_ratio = 200;
dc->caps.i2c_speed_in_khz = 100;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c
index 3d52973dd7f2..6a25dcfcdf17 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c
@@ -497,7 +497,7 @@ static void read_dce_straps(
static struct audio *create_audio(
struct dc_context *ctx, unsigned int inst)
{
- return dce60_audio_create(ctx, inst,
+ return dce_audio_create(ctx, inst,
&audio_regs[inst], &audio_shift, &audio_mask);
}
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c
index 89927727a0d9..33be49b3c1b1 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c
@@ -734,6 +734,7 @@ static struct link_encoder *dce80_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dce110_link_encoder *enc110 =
kzalloc_obj(struct dce110_link_encoder);
int link_regs_id;
@@ -934,7 +935,7 @@ static bool dce80_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = res_cap.num_timing_generator;
pool->base.timing_generator_count = res_cap.num_timing_generator;
dc->caps.max_downscale_ratio = 200;
@@ -1137,7 +1138,7 @@ static bool dce81_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = res_cap_81.num_timing_generator;
pool->base.timing_generator_count = res_cap_81.num_timing_generator;
dc->caps.max_downscale_ratio = 200;
@@ -1337,7 +1338,7 @@ static bool dce83_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = res_cap_83.num_timing_generator;
pool->base.timing_generator_count = res_cap_83.num_timing_generator;
dc->caps.max_downscale_ratio = 200;
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 4663456a736a..0fdebe63d355 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
@@ -764,6 +764,7 @@ static struct link_encoder *dcn10_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn10_link_encoder *enc10 =
kzalloc_obj(struct dcn10_link_encoder);
int link_regs_id;
@@ -1082,6 +1083,7 @@ static enum dc_status build_mapped_resource(
struct dc_state *context,
struct dc_stream_state *stream)
{
+ (void)dc;
struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
if (!pipe_ctx)
@@ -1116,6 +1118,7 @@ static struct pipe_ctx *dcn10_acquire_free_pipe_for_layer(
const struct resource_pool *pool,
const struct pipe_ctx *opp_head_pipe)
{
+ (void)cur_ctx;
struct resource_context *res_ctx = &new_ctx->res_ctx;
struct pipe_ctx *head_pipe = resource_get_otg_master_for_stream(res_ctx, opp_head_pipe->stream);
struct pipe_ctx *idle_pipe = resource_find_free_secondary_pipe_legacy(res_ctx, pool, head_pipe);
@@ -1306,6 +1309,12 @@ static const struct dc_cap_funcs cap_funcs = {
.get_dcc_compression_cap = dcn10_get_dcc_compression_cap
};
+void dcn10_get_default_tiling_info(struct dc_tiling_info *tiling_info)
+{
+ tiling_info->gfxversion = DcGfxVersion9;
+ tiling_info->gfx9.swizzle = DC_SW_LINEAR;
+}
+
static const struct resource_funcs dcn10_res_pool_funcs = {
.destroy = dcn10_destroy_resource_pool,
.link_enc_create = dcn10_link_encoder_create,
@@ -1317,7 +1326,8 @@ static const struct resource_funcs dcn10_res_pool_funcs = {
.add_stream_to_ctx = dcn10_add_stream_to_ctx,
.patch_unknown_plane_state = dcn10_patch_unknown_plane_state,
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static uint32_t read_pipe_fuses(struct dc_context *ctx)
@@ -1372,7 +1382,7 @@ static bool dcn10_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
/* max pipe num for ASIC before check pipe fuses */
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h
index 7bc1be53e800..c7409298caa9 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn10/dcn10_resource.h
@@ -53,5 +53,7 @@ struct stream_encoder *dcn10_find_first_free_match_stream_enc_for_link(
unsigned int dcn10_get_vstartup_for_pipe(struct pipe_ctx *pipe_ctx);
+void dcn10_get_default_tiling_info(struct dc_tiling_info *tiling_info);
+
#endif /* __DC_RESOURCE_DCN10_H__ */
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 74e8d229c9dd..a99829f23965 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
@@ -944,6 +944,7 @@ struct link_encoder *dcn20_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
int link_regs_id;
@@ -1344,6 +1345,7 @@ static enum dc_status build_pipe_hw_param(struct pipe_ctx *pipe_ctx)
enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state *context, struct dc_stream_state *stream)
{
+ (void)dc;
enum dc_status status = DC_OK;
struct pipe_ctx *pipe_ctx = resource_get_otg_master_for_stream(&context->res_ctx, stream);
@@ -1571,6 +1573,7 @@ void dcn20_split_stream_for_mpc(
struct pipe_ctx *primary_pipe,
struct pipe_ctx *secondary_pipe)
{
+ (void)res_ctx;
int pipe_idx = secondary_pipe->pipe_idx;
struct pipe_ctx *sec_bot_pipe = secondary_pipe->bottom_pipe;
@@ -1716,6 +1719,7 @@ struct pipe_ctx *dcn20_find_secondary_pipe(struct dc *dc,
const struct resource_pool *pool,
const struct pipe_ctx *primary_pipe)
{
+ (void)pool;
struct pipe_ctx *secondary_pipe = NULL;
if (dc && primary_pipe) {
@@ -1848,6 +1852,11 @@ void dcn20_merge_pipes_for_validate(
}
}
+static bool is_dual_plane(enum surface_pixel_format format)
+{
+ return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA;
+}
+
int dcn20_validate_apply_pipe_split_flags(
struct dc *dc,
struct dc_state *context,
@@ -1932,8 +1941,15 @@ int dcn20_validate_apply_pipe_split_flags(
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
int pipe_plane = v->pipe_plane[pipe_idx];
- bool split4mpc = context->stream_count == 1 && plane_count == 1
- && dc->config.enable_4to1MPC && dc->res_pool->pipe_count >= 4;
+ bool split4mpc = false;
+
+ if (context->stream_count == 1 && plane_count == 1
+ && dc->config.allow_4to1MPC && dc->res_pool->pipe_count >= 4
+ && !dc->debug.disable_z9_mpc
+ && pipe->plane_state && is_dual_plane(pipe->plane_state->format)
+ && pipe->plane_state->src_rect.width <= 1920
+ && pipe->plane_state->src_rect.height <= 1080)
+ split4mpc = true;
if (!context->res_ctx.pipe_ctx[i].stream)
continue;
@@ -2183,6 +2199,7 @@ struct pipe_ctx *dcn20_acquire_free_pipe_for_layer(
const struct resource_pool *pool,
const struct pipe_ctx *opp_head)
{
+ (void)cur_ctx;
struct resource_context *res_ctx = &new_ctx->res_ctx;
struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(res_ctx, opp_head->stream);
struct pipe_ctx *sec_dpp_pipe = resource_find_free_secondary_pipe_legacy(res_ctx, pool, otg_master);
@@ -2266,7 +2283,8 @@ static const struct resource_funcs dcn20_res_pool_funcs = {
.set_mcif_arb_params = dcn20_set_mcif_arb_params,
.populate_dml_pipes = dcn20_populate_dml_pipes_from_context,
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
bool dcn20_dwbc_create(struct dc_context *ctx, struct resource_pool *pool)
@@ -2364,6 +2382,7 @@ static struct _vcs_dpi_ip_params_st *get_asic_rev_ip_params(
static enum dml_project get_dml_project_version(uint32_t hw_internal_rev)
{
+ (void)hw_internal_rev;
return DML_PROJECT_NAVI10v2;
}
@@ -2375,8 +2394,6 @@ static bool init_soc_bounding_box(struct dc *dc,
struct _vcs_dpi_ip_params_st *loaded_ip =
get_asic_rev_ip_params(dc->ctx->asic_id.hw_internal_rev);
- DC_LOGGER_INIT(dc->ctx->logger);
-
if (pool->base.pp_smu) {
struct pp_smu_nv_clock_table max_clocks = {0};
unsigned int uclk_states[8] = {0};
@@ -2452,7 +2469,7 @@ static bool dcn20_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
dc->caps.max_downscale_ratio = 200;
dc->caps.i2c_speed_in_khz = 100;
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 e289be70efb5..02b7dc07ad53 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
@@ -1114,7 +1114,8 @@ static struct resource_funcs dcn201_res_pool_funcs = {
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.set_mcif_arb_params = dcn20_set_mcif_arb_params,
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static bool dcn201_resource_construct(
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 4333baac96ad..54ebf8cf607f 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
@@ -798,7 +798,8 @@ bool dcn21_fast_validate_bw(struct dc *dc,
int *pipe_cnt_out,
int *pipe_split_from,
int *vlevel_out,
- enum dc_validate_mode validate_mode)
+ enum dc_validate_mode validate_mode,
+ bool allow_self_refresh_only)
{
bool out = false;
int split[MAX_PIPES] = { 0 };
@@ -829,18 +830,23 @@ bool dcn21_fast_validate_bw(struct dc *dc,
vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
if (vlevel > context->bw_ctx.dml.soc.num_states) {
- /*
- * If mode is unsupported or there's still no p-state support then
- * fall back to favoring voltage.
- *
- * We don't actually support prefetch mode 2, so require that we
- * at least support prefetch mode 1.
- */
- context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank =
- dm_allow_self_refresh;
- vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
- if (vlevel > context->bw_ctx.dml.soc.num_states)
+
+ if (allow_self_refresh_only) {
+ /*
+ * If mode is unsupported or there's still no p-state support then
+ * fall back to favoring voltage.
+ *
+ * We don't actually support prefetch mode 2, so require that we
+ * at least support prefetch mode 1.
+ */
+ context->bw_ctx.dml.soc.allow_dram_self_refresh_or_dram_clock_change_in_vblank =
+ dm_allow_self_refresh;
+ vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
+ if (vlevel > context->bw_ctx.dml.soc.num_states)
+ goto validate_fail;
+ } else {
goto validate_fail;
+ }
}
vlevel = dcn20_validate_apply_pipe_split_flags(dc, context, vlevel, split, merge);
@@ -1319,6 +1325,7 @@ static struct link_encoder *dcn21_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn21_link_encoder *enc21 =
kzalloc_obj(struct dcn21_link_encoder);
int link_regs_id;
@@ -1404,7 +1411,8 @@ static const struct resource_funcs dcn21_res_pool_funcs = {
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
.update_bw_bounding_box = dcn21_update_bw_bounding_box,
.get_panel_config_defaults = dcn21_get_panel_config_defaults,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static bool dcn21_resource_construct(
@@ -1427,7 +1435,7 @@ static bool dcn21_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
/* max pipe num for ASIC before check pipe fuses */
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h
index a017fd9854d1..23d3a36872bb 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn21/dcn21_resource.h
@@ -51,6 +51,7 @@ bool dcn21_fast_validate_bw(
int *pipe_cnt_out,
int *pipe_split_from,
int *vlevel_out,
- enum dc_validate_mode validate_mode);
+ enum dc_validate_mode validate_mode,
+ bool allow_self_refresh_only);
#endif /* _DCN21_RESOURCE_H_ */
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 87b7b4ee04c6..4a864689c44f 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
@@ -952,6 +952,7 @@ static struct link_encoder *dcn30_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
@@ -1675,6 +1676,8 @@ noinline bool dcn30_internal_validate_bw(
if (!pipes)
return false;
+ dcn20_merge_pipes_for_validate(dc, context);
+
context->bw_ctx.dml.vba.maxMpcComb = 0;
context->bw_ctx.dml.vba.VoltageLevel = 0;
context->bw_ctx.dml.vba.DRAMClockChangeSupport[0][0] = dm_dram_clock_change_vactive;
@@ -2282,7 +2285,8 @@ static const struct resource_funcs dcn30_res_pool_funcs = {
.update_bw_bounding_box = dcn30_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn30_get_panel_config_defaults,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
#define CTX ctx
@@ -2328,7 +2332,7 @@ static bool dcn30_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 600;
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 6bb1c62124bb..a74b150cbe9c 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
@@ -908,6 +908,7 @@ static struct link_encoder *dcn301_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
@@ -1434,7 +1435,8 @@ static struct resource_funcs dcn301_res_pool_funcs = {
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn301_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info,
};
static bool dcn301_resource_construct(
@@ -1461,7 +1463,7 @@ static bool dcn301_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 600;
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 d02aafd06fd4..539c5aa6bffa 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
@@ -922,6 +922,7 @@ static struct link_encoder *dcn302_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 = kzalloc_obj(struct dcn20_link_encoder);
if (!enc20 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
@@ -1188,7 +1189,8 @@ static struct resource_funcs dcn302_res_pool_funcs = {
.update_bw_bounding_box = dcn302_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn302_get_panel_config_defaults,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static struct dc_cap_funcs cap_funcs = {
@@ -1250,7 +1252,7 @@ static bool dcn302_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->pipe_count = pool->res_cap->num_timing_generator;
pool->mpcc_count = pool->res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 600;
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 30b1403112c6..529eccb4ed3b 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
@@ -867,6 +867,7 @@ static struct link_encoder *dcn303_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 = kzalloc_obj(struct dcn20_link_encoder);
if (!enc20 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
@@ -1132,7 +1133,8 @@ static struct resource_funcs dcn303_res_pool_funcs = {
.update_bw_bounding_box = dcn303_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn303_get_panel_config_defaults,
- .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe
+ .get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static struct dc_cap_funcs cap_funcs = {
@@ -1191,7 +1193,7 @@ static bool dcn303_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->pipe_count = pool->res_cap->num_timing_generator;
pool->mpcc_count = pool->res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 600;
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 4e9c041c707a..ee4bc2c2e73a 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
@@ -1118,6 +1118,7 @@ static struct link_encoder *dcn31_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
@@ -1731,12 +1732,9 @@ int dcn31_populate_dml_pipes_from_context(
pipe_cnt++;
}
context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_1_DEFAULT_DET_SIZE;
- dc->config.enable_4to1MPC = false;
+
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
- if (is_dual_plane(pipe->plane_state->format)
- && pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) {
- dc->config.enable_4to1MPC = true;
- } else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) {
+ if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) {
/* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */
context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192;
pipes[0].pipe.src.unbounded_req_mode = true;
@@ -1883,6 +1881,7 @@ static struct resource_funcs dcn31_res_pool_funcs = {
.get_det_buffer_size = dcn31_get_det_buffer_size,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
+ .get_default_tiling_info = dcn10_get_default_tiling_info,
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
};
@@ -1928,7 +1927,7 @@ static bool dcn31_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 600;
@@ -1953,6 +1952,9 @@ static bool dcn31_resource_construct(
dc->caps.is_apu = true;
dc->caps.zstate_support = true;
+ /* Enable 4to1MPC by default */
+ dc->config.allow_4to1MPC = true;
+
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
dc->caps.color.dpp.input_lut_shared = 0;
@@ -2282,6 +2284,7 @@ enum dc_status dcn31_update_dc_state_for_encoder_switch(struct dc_link *link,
struct pipe_ctx *pipes,
struct audio_output *audio_output)
{
+ (void)link_setting;
struct dc_state *state = link->dc->current_state;
int i;
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 e26a6427916a..5acc545bbe7f 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
@@ -1176,6 +1176,7 @@ static struct link_encoder *dcn31_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
@@ -1814,7 +1815,8 @@ static struct resource_funcs dcn314_res_pool_funcs = {
.get_det_buffer_size = dcn31_get_det_buffer_size,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
- .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
+ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static struct clock_source *dcn30_clock_source_create(
@@ -1858,9 +1860,12 @@ static bool dcn314_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
+
+ /* Enable 4to1MPC by default */
+ dc->config.allow_4to1MPC = true;
dc->caps.max_downscale_ratio = 400;
dc->caps.i2c_speed_in_khz = 100;
dc->caps.i2c_speed_in_khz_hdcp = 100;
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 131a6cd4c735..2ca673114841 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
@@ -1117,6 +1117,7 @@ static struct link_encoder *dcn31_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
@@ -1817,11 +1818,9 @@ static int dcn315_populate_dml_pipes_from_context(
if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_15_MAX_DET_SIZE)
context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_15_MAX_DET_SIZE;
- dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
if (is_dual_plane(pipe->plane_state->format)
&& pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) {
- dc->config.enable_4to1MPC = true;
context->bw_ctx.dml.ip.det_buffer_size_kbytes =
(max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB / 4) * DCN3_15_CRB_SEGMENT_SIZE_KB;
} else if (!is_dual_plane(pipe->plane_state->format)
@@ -1878,7 +1877,8 @@ static struct resource_funcs dcn315_res_pool_funcs = {
.get_det_buffer_size = dcn31_get_det_buffer_size,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
- .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
+ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static bool dcn315_resource_construct(
@@ -1899,8 +1899,11 @@ static bool dcn315_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
+
+ /* Enable 4to1MPC by default */
+ dc->config.allow_4to1MPC = true;
pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 600;
dc->caps.i2c_speed_in_khz = 100;
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 c8c0ce6efcfd..2242df112a3f 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
@@ -1110,6 +1110,7 @@ static struct link_encoder *dcn31_link_encoder_create(
struct dc_context *ctx,
const struct encoder_init_data *enc_init_data)
{
+ (void)ctx;
struct dcn20_link_encoder *enc20 =
kzalloc_obj(struct dcn20_link_encoder);
@@ -1701,11 +1702,9 @@ static int dcn316_populate_dml_pipes_from_context(
if (context->bw_ctx.dml.ip.det_buffer_size_kbytes > DCN3_16_MAX_DET_SIZE)
context->bw_ctx.dml.ip.det_buffer_size_kbytes = DCN3_16_MAX_DET_SIZE;
ASSERT(context->bw_ctx.dml.ip.det_buffer_size_kbytes >= DCN3_16_DEFAULT_DET_SIZE);
- dc->config.enable_4to1MPC = false;
if (pipe_cnt == 1 && pipe->plane_state && !dc->debug.disable_z9_mpc) {
if (is_dual_plane(pipe->plane_state->format)
&& pipe->plane_state->src_rect.width <= 1920 && pipe->plane_state->src_rect.height <= 1080) {
- dc->config.enable_4to1MPC = true;
context->bw_ctx.dml.ip.det_buffer_size_kbytes =
(max_usable_det / DCN3_16_CRB_SEGMENT_SIZE_KB / 4) * DCN3_16_CRB_SEGMENT_SIZE_KB;
} else if (!is_dual_plane(pipe->plane_state->format)) {
@@ -1753,7 +1752,8 @@ static struct resource_funcs dcn316_res_pool_funcs = {
.get_det_buffer_size = dcn31_get_det_buffer_size,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
- .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
+ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static bool dcn316_resource_construct(
@@ -1774,9 +1774,13 @@ static bool dcn316_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
+
+ /* Enable 4to1MPC by default */
+ dc->config.allow_4to1MPC = true;
+
dc->caps.max_downscale_ratio = 600;
dc->caps.i2c_speed_in_khz = 100;
dc->caps.i2c_speed_in_khz_hdcp = 5; /*1.5 w/a applied by default*/
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 c3a6ae14de18..82f81b586986 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
@@ -2147,6 +2147,7 @@ static struct resource_funcs dcn32_res_pool_funcs = {
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
.add_phantom_pipes = dcn32_add_phantom_pipes,
+ .get_default_tiling_info = dcn10_get_default_tiling_info,
.build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
@@ -2225,7 +2226,7 @@ static bool dcn32_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.timing_generator_count = num_pipes;
pool->base.pipe_count = num_pipes;
pool->base.mpcc_count = num_pipes;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
index f5a4e97c40ce..4808c793590f 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource_helpers.c
@@ -41,6 +41,7 @@ uint32_t dcn32_helper_calculate_mall_bytes_for_cursor(
struct pipe_ctx *pipe_ctx,
bool ignore_cursor_buf)
{
+ (void)dc;
struct hubp *hubp = pipe_ctx->plane_res.hubp;
uint32_t cursor_size = hubp->curs_attr.pitch * hubp->curs_attr.height;
uint32_t cursor_mall_size_bytes = 0;
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 990aec7eb3d0..c8c81870d50e 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
@@ -1654,6 +1654,7 @@ static struct resource_funcs dcn321_res_pool_funcs = {
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.get_max_hw_cursor_size = dcn32_get_max_hw_cursor_size,
+ .get_default_tiling_info = dcn10_get_default_tiling_info,
};
static uint32_t read_pipe_fuses(struct dc_context *ctx)
@@ -1729,7 +1730,7 @@ static bool dcn321_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.timing_generator_count = num_pipes;
pool->base.pipe_count = num_pipes;
pool->base.mpcc_count = num_pipes;
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 598b2f25881d..2a1b0b152501 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
@@ -1773,9 +1773,11 @@ static enum dc_status dcn35_validate_bandwidth(struct dc *dc,
{
bool out = false;
+ DC_FP_START();
out = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
validate_mode);
+ DC_FP_END();
if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
@@ -1809,6 +1811,12 @@ static int populate_dml_pipes_from_context_fpu(struct dc *dc,
return ret;
}
+void dcn35_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
+{
+ DC_FP_START();
+ dcn35_update_bw_bounding_box_fpu(dc, bw_params);
+ DC_FP_END();
+}
static struct resource_funcs dcn35_res_pool_funcs = {
.destroy = dcn35_destroy_resource_pool,
.link_enc_create = dcn35_link_encoder_create,
@@ -1830,14 +1838,15 @@ static struct resource_funcs dcn35_res_pool_funcs = {
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
.acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut,
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
- .update_bw_bounding_box = dcn35_update_bw_bounding_box_fpu,
+ .update_bw_bounding_box = dcn35_update_bw_bounding_box,
.patch_unknown_plane_state = dcn35_patch_unknown_plane_state,
.get_panel_config_defaults = dcn35_get_panel_config_defaults,
.get_preferred_eng_id_dpia = dcn35_get_preferred_eng_id_dpia,
.get_det_buffer_size = dcn31_get_det_buffer_size,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
- .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
+ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static bool dcn35_resource_construct(
@@ -1861,6 +1870,9 @@ static bool dcn35_resource_construct(
clk_src_regs_init(3, D),
clk_src_regs_init(4, E);
+ /* Enable 4to1MPC by default */
+ dc->config.allow_4to1MPC = true;
+
#undef REG_STRUCT
#define REG_STRUCT abm_regs
abm_regs_init(0),
@@ -1881,7 +1893,7 @@ static bool dcn35_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 600;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h
index 9c56ae76e0c7..6c2c61c711b9 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.h
@@ -312,4 +312,5 @@ struct resource_pool *dcn35_create_resource_pool(
#define DPP_REG_LIST_DCN35_RI(id)\
DPP_REG_LIST_DCN30_COMMON_RI(id)
+void dcn35_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params);
#endif /* _DCN35_RESOURCE_H_ */
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 7e15d07df7a3..bfd1016aa780 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
@@ -1753,9 +1753,11 @@ static enum dc_status dcn351_validate_bandwidth(struct dc *dc,
{
bool out = false;
+ DC_FP_START();
out = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
validate_mode);
+ DC_FP_END();
if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
@@ -1782,6 +1784,12 @@ static int populate_dml_pipes_from_context_fpu(struct dc *dc,
}
+static void dcn351_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
+{
+ DC_FP_START();
+ dcn351_update_bw_bounding_box_fpu(dc, bw_params);
+ DC_FP_END();
+}
static struct resource_funcs dcn351_res_pool_funcs = {
.destroy = dcn351_destroy_resource_pool,
.link_enc_create = dcn35_link_encoder_create,
@@ -1803,14 +1811,15 @@ static struct resource_funcs dcn351_res_pool_funcs = {
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
.acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut,
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
- .update_bw_bounding_box = dcn351_update_bw_bounding_box_fpu,
+ .update_bw_bounding_box = dcn351_update_bw_bounding_box,
.patch_unknown_plane_state = dcn35_patch_unknown_plane_state,
.get_panel_config_defaults = dcn35_get_panel_config_defaults,
.get_preferred_eng_id_dpia = dcn351_get_preferred_eng_id_dpia,
.get_det_buffer_size = dcn31_get_det_buffer_size,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
- .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
+ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
};
static bool dcn351_resource_construct(
@@ -1834,6 +1843,9 @@ static bool dcn351_resource_construct(
clk_src_regs_init(3, D),
clk_src_regs_init(4, E);
+ /* Enable 4to1MPC by default */
+ dc->config.allow_4to1MPC = true;
+
#undef REG_STRUCT
#define REG_STRUCT abm_regs
abm_regs_init(0),
@@ -1854,7 +1866,7 @@ static bool dcn351_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 600;
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 83fee2ca61bf..07a6675a7329 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
@@ -1760,9 +1760,11 @@ static enum dc_status dcn35_validate_bandwidth(struct dc *dc,
{
bool out = false;
+ DC_FP_START();
out = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
validate_mode);
+ DC_FP_END();
if (validate_mode != DC_VALIDATE_MODE_AND_PROGRAMMING)
return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
@@ -1810,13 +1812,14 @@ static struct resource_funcs dcn36_res_pool_funcs = {
.find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
.acquire_post_bldn_3dlut = dcn30_acquire_post_bldn_3dlut,
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
- .update_bw_bounding_box = dcn35_update_bw_bounding_box_fpu,
+ .update_bw_bounding_box = dcn35_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn35_get_panel_config_defaults,
.get_preferred_eng_id_dpia = dcn36_get_preferred_eng_id_dpia,
.get_vstartup_for_pipe = dcn10_get_vstartup_for_pipe,
.update_dc_state_for_encoder_switch = dcn31_update_dc_state_for_encoder_switch,
- .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params
+ .build_pipe_pix_clk_params = dcn20_build_pipe_pix_clk_params,
+ .get_default_tiling_info = dcn10_get_default_tiling_info,
};
static bool dcn36_resource_construct(
@@ -1860,7 +1863,7 @@ static bool dcn36_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.pipe_count = pool->base.res_cap->num_timing_generator;
pool->base.mpcc_count = pool->base.res_cap->num_timing_generator;
dc->caps.max_downscale_ratio = 600;
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 e37aab939a41..cb93bfbe9e9e 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
@@ -1643,8 +1643,10 @@ static struct dc_cap_funcs cap_funcs = {
.get_subvp_en = dcn32_subvp_in_use,
};
-static void dcn401_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
+static void dcn401_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params)
{
+ dc_assert_fp_enabled();
+
/* re-calculate the available MALL size if required */
if (bw_params->num_channels > 0) {
dc->caps.max_cab_allocation_bytes = dcn401_calc_num_avail_chans_for_mall(
@@ -1653,17 +1655,19 @@ static void dcn401_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b
dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes;
}
- DC_FP_START();
-
if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2)
dml2_reinit(dc, &dc->dml2_options, &dc->current_state->bw_ctx.dml2);
if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2_dc_power_source)
dml2_reinit(dc, &dc->dml2_dc_power_options, &dc->current_state->bw_ctx.dml2_dc_power_source);
+}
+static void dcn401_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
+{
+ DC_FP_START();
+ dcn401_update_bw_bounding_box_fpu(dc, bw_params);
DC_FP_END();
}
-
enum dc_status dcn401_patch_unknown_plane_state(struct dc_plane_state *plane_state)
{
plane_state->tiling_info.gfxversion = DcGfxAddr3;
@@ -1688,10 +1692,13 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc,
}
}
- if (dc->debug.using_dml2)
+ if (dc->debug.using_dml2) {
+ DC_FP_START();
status = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
validate_mode) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
+ DC_FP_END();
+ }
if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING && status == DC_OK && dc_state_is_subvp_in_use(context)) {
/* check new stream configuration still supports cursor if subvp used */
@@ -1710,10 +1717,13 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc,
if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING && status == DC_FAIL_HW_CURSOR_SUPPORT) {
/* attempt to validate again with subvp disabled due to cursor */
- if (dc->debug.using_dml2)
+ if (dc->debug.using_dml2) {
+ DC_FP_START();
status = dml2_validate(dc, context,
context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2,
validate_mode) ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
+ DC_FP_END();
+ }
}
return status;
@@ -1722,9 +1732,13 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc,
void dcn401_prepare_mcache_programming(struct dc *dc,
struct dc_state *context)
{
- if (dc->debug.using_dml21)
+ if (dc->debug.using_dml21) {
+ DC_FP_START();
dml2_prepare_mcache_programming(dc, context,
- context->power_source == DC_POWER_SOURCE_DC ? context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2);
+ context->power_source == DC_POWER_SOURCE_DC ?
+ context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2);
+ DC_FP_END();
+ }
}
static void dcn401_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx)
@@ -1790,7 +1804,7 @@ static void dcn401_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx)
}
}
-static int dcn401_get_power_profile(const struct dc_state *context)
+int dcn401_get_power_profile(const struct dc_state *context)
{
int uclk_mhz = context->bw_ctx.bw.dcn.clk.dramclk_khz / 1000;
int dpm_level = 0;
@@ -1839,9 +1853,16 @@ static struct resource_funcs dcn401_res_pool_funcs = {
.calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
.get_power_profile = dcn401_get_power_profile,
.get_vstartup_for_pipe = dcn401_get_vstartup_for_pipe,
- .get_max_hw_cursor_size = dcn32_get_max_hw_cursor_size
+ .get_max_hw_cursor_size = dcn32_get_max_hw_cursor_size,
+ .get_default_tiling_info = dcn401_get_default_tiling_info
};
+void dcn401_get_default_tiling_info(struct dc_tiling_info *tiling_info)
+{
+ tiling_info->gfxversion = DcGfxAddr3;
+ tiling_info->gfx_addr3.swizzle = DC_ADDR3_SW_LINEAR;
+}
+
static uint32_t read_pipe_fuses(struct dc_context *ctx)
{
uint32_t value = REG_READ(CC_DC_PIPE_DIS);
@@ -1908,7 +1929,7 @@ static bool dcn401_resource_construct(
/*************************************************
* Resource + asic cap harcoding *
*************************************************/
- pool->base.underlay_pipe_index = NO_UNDERLAY_PIPE;
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
pool->base.timing_generator_count = num_pipes;
pool->base.pipe_count = num_pipes;
pool->base.mpcc_count = num_pipes;
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 08bec1755617..47f82b818262 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
@@ -28,8 +28,11 @@ enum dc_status dcn401_validate_bandwidth(struct dc *dc,
void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context);
+void dcn401_get_default_tiling_info(struct dc_tiling_info *tiling_info);
+
unsigned int dcn401_get_vstartup_for_pipe(struct pipe_ctx *pipe_ctx);
+int dcn401_get_power_profile(const struct dc_state *context);
/* Following are definitions for run time init of reg offsets */
/* HUBP */
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
new file mode 100644
index 000000000000..c0d37f00fed9
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.c
@@ -0,0 +1,2358 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "dm_services.h"
+#include "dc.h"
+
+#include "dcn32/dcn32_init.h"
+#include "dcn42/dcn42_init.h"
+
+#include "resource.h"
+#include "include/irq_service_interface.h"
+
+#include "dcn42_resource.h"
+#include "dcn42_resource_fpu.h"
+#include "dcn20/dcn20_resource.h"
+#include "dcn30/dcn30_resource.h"
+#include "dcn31/dcn31_resource.h"
+#include "dcn32/dcn32_resource.h"
+#include "dcn35/dcn35_resource.h"
+#include "dcn321/dcn321_resource.h"
+#include "dcn401/dcn401_resource.h"
+
+#include "dcn10/dcn10_ipp.h"
+#include "dcn35/dcn35_hubbub.h"
+#include "dcn42/dcn42_hubbub.h"
+#include "dcn401/dcn401_mpc.h"
+#include "dcn42/dcn42_mpc.h"
+#include "dcn35/dcn35_hubp.h"
+#include "dcn42/dcn42_hubp.h"
+#include "irq/dcn42/irq_service_dcn42.h"
+#include "dcn42/dcn42_dpp.h"
+#include "dcn401/dcn401_dsc.h"
+#include "dcn42/dcn42_optc.h"
+#include "dcn20/dcn20_hwseq.h"
+#include "dcn30/dcn30_hwseq.h"
+#include "dce110/dce110_hwseq.h"
+#include "dcn35/dcn35_opp.h"
+#include "dcn30/dcn30_vpg.h"
+#include "dcn31/dcn31_vpg.h"
+#include "dcn42/dcn42_dio_stream_encoder.h"
+#include "dcn42/dcn42_pg_cntl.h"
+#include "dcn31/dcn31_hpo_dp_stream_encoder.h"
+#include "dcn31/dcn31_hpo_dp_link_encoder.h"
+#include "dcn32/dcn32_hpo_dp_link_encoder.h"
+#include "dcn42/dcn42_hpo_dp_link_encoder.h"
+#include "dcn31/dcn31_apg.h"
+#include "dcn31/dcn31_dio_link_encoder.h"
+#include "dcn401/dcn401_dio_link_encoder.h"
+#include "dcn10/dcn10_link_encoder.h"
+#include "dcn321/dcn321_dio_link_encoder.h"
+#include "dce/dce_clock_source.h"
+#include "dce/dce_audio.h"
+#include "dce/dce_hwseq.h"
+#include "clk_mgr.h"
+#include "dio/virtual/virtual_stream_encoder.h"
+#include "dml/display_mode_vba.h"
+#include "dcn42/dcn42_dccg.h"
+#include "dcn10/dcn10_resource.h"
+#include "link_service.h"
+#include "dcn31/dcn31_panel_cntl.h"
+
+#include "dcn30/dcn30_dwb.h"
+#include "dcn42/dcn42_mmhubbub.h"
+#include "dcn42/dcn42_dio_link_encoder.h"
+
+#include "dcn/dcn_4_2_0_offset.h"
+#include "dcn/dcn_4_2_0_sh_mask.h"
+#include "dpcs/dpcs_4_0_0_offset.h"
+#include "dpcs/dpcs_4_0_0_sh_mask.h"
+
+#include "reg_helper.h"
+#include "dce/dmub_abm.h"
+#include "dce/dmub_psr.h"
+#include "dce/dmub_replay.h"
+#include "dce/dce_aux.h"
+#include "dce/dce_i2c.h"
+
+#include "dml/dcn30/display_mode_vba_30.h"
+#include "vm_helper.h"
+#include "dcn20/dcn20_vmid.h"
+
+#include "dc_state_priv.h"
+#include "link_enc_cfg.h"
+
+#include "dml2_0/dml2_wrapper.h"
+
+#define regBIF_BX0_BIOS_SCRATCH_3 0x003b
+#define regBIF_BX0_BIOS_SCRATCH_3_BASE_IDX 1
+#define regBIF_BX0_BIOS_SCRATCH_6 0x003e
+#define regBIF_BX0_BIOS_SCRATCH_6_BASE_IDX 1
+
+#define DC_LOGGER_INIT(logger)
+
+enum dcn401_clk_src_array_id {
+ DCN401_CLK_SRC_PLL0,
+ DCN401_CLK_SRC_PLL1,
+ DCN401_CLK_SRC_PLL2,
+ DCN401_CLK_SRC_PLL3,
+ DCN401_CLK_SRC_PLL4,
+ DCN401_CLK_SRC_TOTAL
+};
+
+/* begin
+ * macros to expend register list macro defined in HW object header file
+ */
+
+/* DCN */
+#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg]
+
+#define BASE(seg) BASE_INNER(seg)
+
+#define SR(reg_name) \
+ REG_STRUCT.reg_name = BASE(reg##reg_name##_BASE_IDX) + \
+ reg##reg_name
+#define SR_ARR(reg_name, id) \
+ REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + \
+ reg##reg_name
+#define SR_ARR_INIT(reg_name, id, value) \
+ REG_STRUCT[id].reg_name = value
+
+#define SRI(reg_name, block, id) \
+ REG_STRUCT.reg_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+ reg##block##id##_##reg_name
+
+#define SRI_ARR(reg_name, block, id) \
+ REG_STRUCT[id].reg_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+ reg##block##id##_##reg_name
+
+/*
+ * Used when a reg_name would otherwise begin with an integer
+ */
+#define SRI_ARR_US(reg_name, block, id) \
+ REG_STRUCT[id].reg_name = BASE(reg##block##id##reg_name##_BASE_IDX) + \
+ reg##block##id##reg_name
+#define SR_ARR_I2C(reg_name, id) \
+ REG_STRUCT[id - 1].reg_name = BASE(reg##reg_name##_BASE_IDX) + reg##reg_name
+
+#define SRI_ARR_I2C(reg_name, block, id) \
+ REG_STRUCT[id - 1].reg_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+ reg##block##id##_##reg_name
+
+
+#define SRI_ARR_ALPHABET(reg_name, block, index, id) \
+ REG_STRUCT[index].reg_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+ reg##block##id##_##reg_name
+
+#define SRI2(reg_name, block, id) \
+ .reg_name = BASE(reg##reg_name##_BASE_IDX) + \
+ reg##reg_name
+#define SRI2_ARR(reg_name, block, id) \
+ REG_STRUCT[id].reg_name = BASE(reg##reg_name##_BASE_IDX) + \
+ reg##reg_name
+
+#define SRIR(var_name, reg_name, block, id) \
+ .var_name = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+ reg##block##id##_##reg_name
+
+#define SRII(reg_name, block, id) \
+ REG_STRUCT.reg_name[id] = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+ reg##block##id##_##reg_name
+
+#define SRII_ARR_2(reg_name, block, id, inst) \
+ REG_STRUCT[inst].reg_name[id] = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+ reg##block##id##_##reg_name
+
+#define SRII_MPC_RMU(reg_name, block, id) \
+ .RMU##_##reg_name[id] = BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+ reg##block##id##_##reg_name
+
+#define SRII_DWB(reg_name, temp_name, block, id) \
+ REG_STRUCT.reg_name[id] = \
+ BASE(reg##block##id##_##temp_name##_BASE_IDX) + \
+ reg##block##id##_##temp_name
+
+#define DCCG_SRII(reg_name, block, id) \
+ REG_STRUCT.block##_##reg_name[id] = \
+ BASE(reg##block##id##_##reg_name##_BASE_IDX) + \
+ reg##block##id##_##reg_name
+
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+ .field_name = reg_name##__##field_name##post_fix
+
+#define VUPDATE_SRII(reg_name, block, id) \
+ REG_STRUCT.reg_name[id] = BASE(reg##reg_name##_##block##id##_BASE_IDX) + \
+ reg##reg_name##_##block##id
+
+/* NBIO */
+#define NBIO_BASE_INNER(seg) ctx->nbio_reg_offsets[seg]
+
+#define NBIO_BASE(seg) \
+ NBIO_BASE_INNER(seg)
+
+#define NBIO_SR(reg_name) \
+ REG_STRUCT.reg_name = NBIO_BASE(regBIF_BX0_##reg_name##_BASE_IDX) + \
+ regBIF_BX0_##reg_name
+#define NBIO_SR_ARR(reg_name, id) \
+ REG_STRUCT[id].reg_name = NBIO_BASE(regBIF_BX0_##reg_name##_BASE_IDX) + \
+ regBIF_BX0_##reg_name
+
+#define CTX ctx
+#define REG(reg_name) \
+ (ctx->dcn_reg_offsets[reg##reg_name##_BASE_IDX] + reg##reg_name)
+
+static struct bios_registers bios_regs;
+
+#define bios_regs_init() \
+ NBIO_SR(BIOS_SCRATCH_3), \
+ NBIO_SR(BIOS_SCRATCH_6)
+
+#define clk_src_regs_init(index, pllid) \
+ CS_COMMON_REG_LIST_DCN42_RI(index, pllid)
+
+static struct dce110_clk_src_regs clk_src_regs[5];
+
+static const struct dce110_clk_src_shift cs_shift = {
+ CS_COMMON_MASK_SH_LIST_DCN3_1_4(__SHIFT)
+};
+static const struct dce110_clk_src_mask cs_mask = {
+ CS_COMMON_MASK_SH_LIST_DCN3_1_4(_MASK)
+};
+#define abm_regs_init(id) \
+ ABM_DCN42_REG_LIST_RI(id)
+
+static struct dce_abm_registers abm_regs[4];
+
+static const struct dce_abm_shift abm_shift = {
+ ABM_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dce_abm_mask abm_mask = {
+ ABM_MASK_SH_LIST_DCN42(_MASK)};
+
+#define audio_regs_init(id) \
+ AUD_COMMON_REG_LIST_RI(id)
+
+static struct dce_audio_registers audio_regs[5];
+
+static const struct dce_audio_shift audio_shift = {
+ DCN42_AUD_COMMON_MASK_SH_LIST(__SHIFT)
+};
+
+static const struct dce_audio_mask audio_mask = {
+ DCN42_AUD_COMMON_MASK_SH_LIST(_MASK)
+};
+
+#define vpg_regs_init(id) \
+ VPG_DCN401_REG_LIST_RI(id)
+
+static struct dcn31_vpg_registers vpg_regs[10];
+
+static const struct dcn31_vpg_shift vpg_shift = {
+ DCN31_VPG_MASK_SH_LIST(__SHIFT)};
+
+static const struct dcn31_vpg_mask vpg_mask = {
+ DCN31_VPG_MASK_SH_LIST(_MASK)};
+
+#define apg_regs_init(id) \
+ APG_DCN31_REG_LIST_RI(id)
+
+static struct dcn31_apg_registers apg_regs[10];
+
+static const struct dcn31_apg_shift apg_shift = {
+ DCN31_APG_MASK_SH_LIST(__SHIFT)};
+
+static const struct dcn31_apg_mask apg_mask = {
+ DCN31_APG_MASK_SH_LIST(_MASK)};
+
+#define stream_enc_regs_init(id) \
+ SE_DCN42_REG_LIST_RI(id)
+
+static struct dcn10_stream_enc_registers stream_enc_regs[5];
+
+static const struct dcn10_stream_encoder_shift se_shift = {
+ SE_COMMON_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dcn10_stream_encoder_mask se_mask = {
+ SE_COMMON_MASK_SH_LIST_DCN42(_MASK)};
+
+#define aux_regs_init(id) \
+ DCN2_AUX_REG_LIST_RI(id)
+
+static struct dcn10_link_enc_aux_registers link_enc_aux_regs[5];
+
+#define hpd_regs_init(id) \
+ HPD_REG_LIST_RI(id)
+
+static struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[5];
+
+#define link_regs_init(id, phyid) \
+ LE_DCN401_REG_LIST_RI(id)
+
+static struct dcn10_link_enc_registers link_enc_regs[5];
+
+static const struct dcn10_link_enc_shift le_shift = {
+ LINK_ENCODER_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dcn10_link_enc_mask le_mask = {
+ LINK_ENCODER_MASK_SH_LIST_DCN42(_MASK)};
+
+#define hpo_dp_stream_encoder_reg_init(id) \
+ DCN42_HPO_DP_STREAM_ENC_REG_LIST_RI(id)
+
+static struct dcn31_hpo_dp_stream_encoder_registers hpo_dp_stream_enc_regs[4];
+
+static const struct dcn31_hpo_dp_stream_encoder_shift hpo_dp_se_shift = {
+ DCN4_2_HPO_DP_STREAM_ENC_MASK_SH_LIST(__SHIFT)};
+
+static const struct dcn31_hpo_dp_stream_encoder_mask hpo_dp_se_mask = {
+ DCN4_2_HPO_DP_STREAM_ENC_MASK_SH_LIST(_MASK)};
+
+#define hpo_dp_link_encoder_reg_init(id) \
+ DCN42_HPO_DP_LINK_ENC_REG_LIST_RI(id)
+
+static struct dcn31_hpo_dp_link_encoder_registers hpo_dp_link_enc_regs[4];
+
+static const struct dcn31_hpo_dp_link_encoder_shift hpo_dp_le_shift = {
+ DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(__SHIFT)};
+
+static const struct dcn31_hpo_dp_link_encoder_mask hpo_dp_le_mask = {
+ DCN3_2_HPO_DP_LINK_ENC_MASK_SH_LIST(_MASK)};
+
+#define dpp_regs_init(id) \
+ DPP_REG_LIST_DCN42_COMMON_RI(id)
+
+static struct dcn42_dpp_registers dpp_regs[4];
+
+static const struct dcn42_dpp_shift tf_shift = {
+ DPP_REG_LIST_SH_MASK_DCN42_COMMON(__SHIFT)};
+
+static const struct dcn42_dpp_mask tf_mask = {
+ DPP_REG_LIST_SH_MASK_DCN42_COMMON(_MASK)};
+
+#define opp_regs_init(id) \
+ OPP_REG_LIST_DCN401_RI(id)
+
+static struct dcn20_opp_registers opp_regs[4];
+
+static const struct dcn20_opp_shift opp_shift = {
+ OPP_MASK_SH_LIST_DCN20(__SHIFT)};
+
+static const struct dcn20_opp_mask opp_mask = {
+ OPP_MASK_SH_LIST_DCN20(_MASK)};
+
+#define aux_engine_regs_init(id) \
+ AUX_COMMON_REG_LIST0_RI(id), SR_ARR_INIT(AUXN_IMPCAL, id, 0), \
+ SR_ARR_INIT(AUXP_IMPCAL, id, 0), \
+ SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK), \
+ SR_ARR_INIT(AUX_RESET_MASK, id, DP_AUX0_AUX_CONTROL__AUX_RESET_MASK)
+
+static struct dce110_aux_registers aux_engine_regs[5];
+
+static const struct dce110_aux_registers_shift aux_shift = {
+ DCN_AUX_MASK_SH_LIST(__SHIFT)};
+
+static const struct dce110_aux_registers_mask aux_mask = {
+ DCN_AUX_MASK_SH_LIST(_MASK)};
+
+#define dwbc_regs_dcn401_init(id) \
+ DWBC_COMMON_REG_LIST_DCN30_RI(id)
+
+static struct dcn30_dwbc_registers dwbc401_regs[1];
+
+static const struct dcn30_dwbc_shift dwbc401_shift = {
+ DWBC_COMMON_MASK_SH_LIST_DCN30(__SHIFT)};
+
+static const struct dcn30_dwbc_mask dwbc401_mask = {
+ DWBC_COMMON_MASK_SH_LIST_DCN30(_MASK)};
+
+#define mcif_wb_regs_dcn3_init(id) \
+ MCIF_WB_COMMON_REG_LIST_DCN3_5_RI(id)
+
+static struct dcn35_mmhubbub_registers mcif_wb35_regs[1];
+
+static const struct dcn35_mmhubbub_shift mcif_wb35_shift = {
+ MCIF_WB_COMMON_MASK_SH_LIST_DCN3_5(__SHIFT)};
+
+static const struct dcn35_mmhubbub_mask mcif_wb35_mask = {
+ MCIF_WB_COMMON_MASK_SH_LIST_DCN3_5(_MASK)};
+
+#define dsc_regs_init(id) \
+ DSC_REG_LIST_DCN401_RI(id)
+
+static struct dcn401_dsc_registers dsc_regs[4];
+
+static const struct dcn401_dsc_shift dsc_shift = {
+ DSC_REG_LIST_SH_MASK_DCN401(__SHIFT)};
+
+static const struct dcn401_dsc_mask dsc_mask = {
+ DSC_REG_LIST_SH_MASK_DCN401(_MASK)};
+
+static struct dcn42_mpc_registers mpc_regs;
+
+#define dcn_mpc_regs_init() \
+ MPC_REG_LIST_DCN42(0), \
+ MPC_REG_LIST_DCN42(1), \
+ MPC_REG_LIST_DCN42(2), \
+ MPC_REG_LIST_DCN42(3), \
+ MPC_OUT_MUX_REG_LIST_DCN3_0_RI(0), \
+ MPC_OUT_MUX_REG_LIST_DCN3_0_RI(1), \
+ MPC_OUT_MUX_REG_LIST_DCN3_0_RI(2), \
+ MPC_OUT_MUX_REG_LIST_DCN3_0_RI(3), \
+ MPC_DWB_MUX_REG_LIST_DCN3_0_RI(0), \
+ MPC_RMCM_REG_LIST_DCN42(0), \
+ MPC_RMCM_REG_LIST_DCN42(1)
+
+static const struct dcn42_mpc_shift mpc_shift = {
+ MPC_COMMON_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dcn42_mpc_mask mpc_mask = {
+ MPC_COMMON_MASK_SH_LIST_DCN42(_MASK)};
+
+#define optc_regs_init(id) \
+ OPTC_COMMON_REG_LIST_DCN42_RI(id)
+
+static struct dcn_optc_registers optc_regs[4];
+
+static const struct dcn_optc_shift optc_shift = {
+ OPTC_COMMON_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dcn_optc_mask optc_mask = {
+ OPTC_COMMON_MASK_SH_LIST_DCN42(_MASK)};
+
+#define hubp_regs_init(id) \
+ HUBP_REG_LIST_DCN42_RI(id)
+
+static struct dcn_hubp2_registers hubp_regs[4];
+
+static const struct dcn_hubp2_shift hubp_shift = {
+ HUBP_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dcn_hubp2_mask hubp_mask = {
+ HUBP_MASK_SH_LIST_DCN42(_MASK)};
+
+static struct dcn_hubbub_registers hubbub_reg;
+
+#define hubbub_reg_init() \
+ HUBBUB_REG_LIST_DCN42(0)
+
+static const struct dcn_hubbub_shift hubbub_shift = {
+ HUBBUB_MASK_SH_LIST_DCN4_2(__SHIFT)};
+
+static const struct dcn_hubbub_mask hubbub_mask = {
+ HUBBUB_MASK_SH_LIST_DCN4_2(_MASK)};
+
+static struct dccg_registers dccg_regs;
+
+#define dccg_regs_init() \
+ DCCG_REG_LIST_DCN42_RI()
+
+static const struct dccg_shift dccg_shift = {
+ DCCG_MASK_SH_LIST_DCN42(__SHIFT)};
+
+static const struct dccg_mask dccg_mask = {
+ DCCG_MASK_SH_LIST_DCN42(_MASK)};
+
+static struct pg_cntl_registers pg_cntl_regs;
+
+#define pg_cntl_dcn42_regs_init() \
+ PG_CNTL_REG_LIST_DCN42()
+
+static const struct pg_cntl_shift pg_cntl_shift = {
+ PG_CNTL_MASK_SH_LIST_DCN42(__SHIFT)
+};
+
+static const struct pg_cntl_mask pg_cntl_mask = {
+ PG_CNTL_MASK_SH_LIST_DCN42(_MASK)
+};
+#define SRII2(reg_name_pre, reg_name_post, id) \
+ .reg_name_pre##_##reg_name_post[id] = \
+ BASE(reg##reg_name_pre##id##_##reg_name_post##_BASE_IDX) + \
+ reg##reg_name_pre##id##_##reg_name_post
+
+#define HWSEQ_DCN42_REG_LIST() \
+ SR(DCHUBBUB_GLOBAL_TIMER_CNTL), \
+ SR(DIO_MEM_PWR_CTRL), \
+ SR(ODM_MEM_PWR_CTRL3), \
+ SR(MMHUBBUB_MEM_PWR_CNTL), \
+ SR(DCCG_GATE_DISABLE_CNTL), \
+ SR(DCCG_GATE_DISABLE_CNTL2), \
+ SR(DCFCLK_CNTL), \
+ SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \
+ SRII(PIXEL_RATE_CNTL, OTG, 0), \
+ SRII(PIXEL_RATE_CNTL, OTG, 1), \
+ SRII(PIXEL_RATE_CNTL, OTG, 2), \
+ SRII(PIXEL_RATE_CNTL, OTG, 3),\
+ SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 0), \
+ SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 1), \
+ SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 2), \
+ SRII(PHYPLL_PIXEL_RATE_CNTL, OTG, 3),\
+ SR(MICROSECOND_TIME_BASE_DIV), \
+ SR(MILLISECOND_TIME_BASE_DIV), \
+ SR(DISPCLK_FREQ_CHANGE_CNTL), \
+ SR(RBBMIF_TIMEOUT_DIS), \
+ SR(RBBMIF_TIMEOUT_DIS_2), \
+ SR(DCHUBBUB_CRC_CTRL), \
+ SR(DPP_TOP0_DPP_CRC_CTRL), \
+ SR(DPP_TOP0_DPP_CRC_VAL_R), \
+ SR(DPP_TOP0_DPP_CRC_VAL_G), \
+ SR(DPP_TOP0_DPP_CRC_VAL_B), \
+ SR(MPC_CRC_CTRL), \
+ SR(MPC_CRC_RESULT_R), \
+ SR(MPC_CRC_RESULT_G), \
+ SR(MPC_CRC_RESULT_B), \
+ SR(MPC_CRC_RESULT_A), \
+ SR(DOMAIN0_PG_CONFIG), \
+ SR(DOMAIN1_PG_CONFIG), \
+ SR(DOMAIN2_PG_CONFIG), \
+ SR(DOMAIN3_PG_CONFIG), \
+ SR(DOMAIN16_PG_CONFIG), \
+ SR(DOMAIN17_PG_CONFIG), \
+ SR(DOMAIN18_PG_CONFIG), \
+ SR(DOMAIN19_PG_CONFIG), \
+ SR(DOMAIN22_PG_CONFIG), \
+ SR(DOMAIN23_PG_CONFIG), \
+ SR(DOMAIN24_PG_CONFIG), \
+ SR(DOMAIN25_PG_CONFIG), \
+ SR(DOMAIN26_PG_CONFIG), \
+ SR(DOMAIN0_PG_STATUS), \
+ SR(DOMAIN1_PG_STATUS), \
+ SR(DOMAIN2_PG_STATUS), \
+ SR(DOMAIN3_PG_STATUS), \
+ SR(DOMAIN16_PG_STATUS), \
+ SR(DOMAIN17_PG_STATUS), \
+ SR(DOMAIN18_PG_STATUS), \
+ SR(DOMAIN19_PG_STATUS), \
+ SR(DOMAIN22_PG_STATUS), \
+ SR(DOMAIN23_PG_STATUS), \
+ SR(DOMAIN24_PG_STATUS), \
+ SR(DOMAIN25_PG_STATUS), \
+ SR(DOMAIN26_PG_STATUS), \
+ SR(DC_IP_REQUEST_CNTL), \
+ SR(AZALIA_AUDIO_DTO), \
+ SR(HPO_TOP_HW_CONTROL), \
+ SR(AZALIA_CONTROLLER_CLOCK_GATING)
+
+static struct dce_hwseq_registers hwseq_reg;
+
+#define hwseq_reg_init() \
+ HWSEQ_DCN42_REG_LIST()
+
+#define HWSEQ_DCN42_MASK_SH_LIST(mask_sh) \
+ HWSEQ_DCN_MASK_SH_LIST(mask_sh), \
+ HWS_SF(, DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_REFDIV, mask_sh), \
+ HWS_SF(, DCHUBBUB_ARB_HOSTVM_CNTL, DISABLE_HOSTVM_FORCE_ALLOW_PSTATE, mask_sh), \
+ HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN0_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN1_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN2_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN3_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN16_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN17_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN18_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN19_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN22_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN22_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN23_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN23_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN24_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN24_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN25_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN25_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN26_PG_CONFIG, DOMAIN_POWER_FORCEON, mask_sh), \
+ HWS_SF(, DOMAIN26_PG_CONFIG, DOMAIN_POWER_GATE, mask_sh), \
+ HWS_SF(, DOMAIN0_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN1_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN2_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN3_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN16_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN17_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN18_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN19_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN22_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN23_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN24_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN25_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DOMAIN26_PG_STATUS, DOMAIN_PGFSM_PWR_STATUS, mask_sh), \
+ HWS_SF(, DC_IP_REQUEST_CNTL, IP_REQUEST_EN, mask_sh), \
+ HWS_SF(, AZALIA_AUDIO_DTO, AZALIA_AUDIO_DTO_MODULE, mask_sh), \
+ HWS_SF(, HPO_TOP_CLOCK_CONTROL, HPO_HDMISTREAMCLK_G_GATE_DIS, mask_sh), \
+ HWS_SF(, HPO_TOP_HW_CONTROL, HPO_IO_EN, mask_sh), \
+ HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_UNASSIGNED_PWR_MODE, mask_sh), \
+ HWS_SF(, ODM_MEM_PWR_CTRL3, ODM_MEM_VBLANK_PWR_MODE, mask_sh), \
+ HWS_SF(, DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, mask_sh), \
+ HWS_SF(, DMU_CLK_CNTL, DISPCLK_R_DMU_GATE_DIS, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DISPCLK_G_RBBMIF_GATE_DIS, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, RBBMIF_FGCG_REP_DIS, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DPREFCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DISPCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DPPCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DTBCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DCFCLK_ALLOW_DS_CLKSTOP, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, DPIACLK_ALLOW_DS_CLKSTOP, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, LONO_FGCG_REP_DIS, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, LONO_DISPCLK_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, LONO_SOCCLK_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DMU_CLK_CNTL, LONO_DMCUBCLK_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_FE_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_FE_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_FE_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_FE_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_FE_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, HDMICHARCLK0_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKA_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKB_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKC_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKD_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, SYMCLKE_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, mask_sh), \
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK0_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK1_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK2_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL5, DPSTREAMCLK3_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK0_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK1_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK2_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK3_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK4_GATE_DISABLE, mask_sh),\
+ HWS_SF(, DCCG_GATE_DISABLE_CNTL4, DPIASYMCLK5_GATE_DISABLE, mask_sh)
+
+static const struct dce_hwseq_shift hwseq_shift = {
+ HWSEQ_DCN42_MASK_SH_LIST(__SHIFT)};
+
+static const struct dce_hwseq_mask hwseq_mask = {
+ HWSEQ_DCN42_MASK_SH_LIST(_MASK)};
+
+#define vmid_regs_init(id) \
+ DCN20_VMID_REG_LIST_RI(id)
+
+static struct dcn_vmid_registers vmid_regs[16];
+
+static const struct dcn20_vmid_shift vmid_shifts = {
+ DCN20_VMID_MASK_SH_LIST(__SHIFT)};
+
+static const struct dcn20_vmid_mask vmid_masks = {
+ DCN20_VMID_MASK_SH_LIST(_MASK)};
+
+static const struct resource_caps res_cap_dcn42 = {
+ .num_timing_generator = 4,
+ .num_opp = 4,
+ .num_dpp = 4,
+ .num_video_plane = 4,
+ .num_audio = 5,
+ .num_stream_encoder = 5,
+ .num_dig_link_enc = 5,
+ .num_usb4_dpia = 6,
+ .num_hpo_dp_stream_encoder = 4,
+ .num_hpo_dp_link_encoder = 4,
+ .num_pll = 5,
+ .num_dwb = 1,
+ .num_ddc = 5,
+ .num_vmid = 16,
+ .num_mpc_3dlut = 2,
+ .num_dsc = 4,
+ .num_rmcm = 2,
+};
+
+static const struct dc_plane_cap plane_cap = {
+ .type = DC_PLANE_TYPE_DCN_UNIVERSAL,
+ .per_pixel_alpha = true,
+
+ .pixel_format_support = {
+ .argb8888 = true,
+ .nv12 = true,
+ .fp16 = true,
+ .p010 = true,
+ .ayuv = false,
+ },
+
+ .max_upscale_factor = {.argb8888 = 16000, .nv12 = 16000, .fp16 = 16000},
+
+ // 6:1 downscaling ratio: 1000/6 = 166.666
+ .max_downscale_factor = {.argb8888 = 167, .nv12 = 167, .fp16 = 167},
+
+ .min_width = 64,
+ .min_height = 64};
+
+static const struct dc_debug_options debug_defaults_drv = {
+ .disable_dmcu = true,
+ .force_abm_enable = false,
+ .clock_trace = true,
+ .disable_pplib_clock_request = false,
+ .disable_dpp_power_gate = true,
+ .disable_hubp_power_gate = true,
+ .disable_optc_power_gate = true,
+ .pipe_split_policy = MPC_SPLIT_AVOID,
+ .force_single_disp_pipe_split = false,
+ .disable_dcc = DCC_ENABLE,
+ .vsr_support = true,
+ .performance_trace = false,
+ .max_downscale_src_width = 4096, /*up to 4K for APU*/
+ .disable_pplib_wm_range = false,
+ .scl_reset_length10 = true,
+ .sanity_checks = false,
+ .underflow_assert_delay_us = 0xFFFFFFFF,
+ .dwb_fi_phase = -1, // -1 = disable,
+ .dmub_command_table = true,
+ .pstate_enabled = true,
+ .enable_mem_low_power = {
+ .bits = {
+ .vga = false,
+ .i2c = true,
+ .dscl = true,
+ .cm = true,
+ .mpc = true,
+ .optc = true,
+ .vpg = true,
+ }},
+ .root_clock_optimization = {
+ .bits = {
+ .dpp = true,
+ .dsc = true,/*dscclk and dsc pg*/
+ .hdmistream = false,
+ .hdmichar = true,
+ .dpstream = true,
+ .symclk32_se = true,
+ .symclk32_le = true,
+ .symclk_fe = true,
+ .physymclk = false,
+ .dpiasymclk = true,
+ }
+ },
+ .seamless_boot_odm_combine = DML_FAIL_SOURCE_PIXEL_FORMAT,
+ .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/
+ .minimum_z8_residency_time = 1, /* Always allow when other conditions are met */
+ .support_eDP1_5 = true,
+ .use_max_lb = true,
+ .force_disable_subvp = false,
+ .exit_idle_opt_for_cursor_updates = true,
+ .using_dml2 = true,
+ .using_dml21 = true,
+ .enable_single_display_2to1_odm_policy = true,
+
+ // must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions
+ .enable_double_buffered_dsc_pg_support = true,
+ .enable_dp_dig_pixel_rate_div_policy = 1,
+ .allow_sw_cursor_fallback = false,
+ .psp_disabled_wa = true,
+ .alloc_extra_way_for_cursor = true,
+ .min_prefetch_in_strobe_ns = 60000, // 60us
+ .disable_unbounded_requesting = false,
+ .dcc_meta_propagation_delay_us = 10,
+ .disable_timeout = true,
+ .min_disp_clk_khz = 50000,
+ .static_screen_wait_frames = 2,
+ .disable_z10 = false,
+ .ignore_pg = true,
+ .disable_stutter_for_wm_program = true,
+ .min_deep_sleep_dcfclk_khz = 8000,
+ .replay_skip_crtc_disabled = true,
+ .psr_skip_crtc_disable = true,
+};
+
+static const struct dc_check_config config_defaults = {
+ .enable_legacy_fast_update = false,
+};
+
+static struct dce_aux *dcn42_aux_engine_create(
+ struct dc_context *ctx,
+ uint32_t inst)
+{
+ struct aux_engine_dce110 *aux_engine =
+ kzalloc(sizeof(struct aux_engine_dce110), GFP_KERNEL);
+
+ if (!aux_engine)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT aux_engine_regs
+ aux_engine_regs_init(0),
+ aux_engine_regs_init(1),
+ aux_engine_regs_init(2),
+ aux_engine_regs_init(3),
+ aux_engine_regs_init(4);
+
+ dce110_aux_engine_construct(aux_engine, ctx, inst,
+ SW_AUX_TIMEOUT_PERIOD_MULTIPLIER * AUX_TIMEOUT_PERIOD,
+ &aux_engine_regs[inst],
+ &aux_mask,
+ &aux_shift,
+ ctx->dc->caps.extended_aux_timeout_support);
+
+ return &aux_engine->base;
+}
+
+#define i2c_inst_regs_init(id) \
+ I2C_HW_ENGINE_COMMON_REG_LIST_DCN30_RI(id)
+
+static struct dce_i2c_registers i2c_hw_regs[5];
+
+static const struct dce_i2c_shift i2c_shifts = {
+ I2C_COMMON_MASK_SH_LIST_DCN35(__SHIFT)
+};
+static const struct dce_i2c_mask i2c_masks = {
+ I2C_COMMON_MASK_SH_LIST_DCN35(_MASK)
+};
+
+/* ========================================================== */
+
+/*
+ * DPIA index | Preferred Encoder | Host Router
+ * 0 | C | 0
+ * 1 | First Available | 0
+ * 2 | D | 1
+ * 3 | First Available | 1
+ * 4 | E | 2
+ * 5 | First Available | 2
+ */
+/* ========================================================== */
+static const enum engine_id dpia_to_preferred_enc_id_table[] = {
+ ENGINE_ID_DIGC,
+ ENGINE_ID_DIGC,
+ ENGINE_ID_DIGD,
+ ENGINE_ID_DIGD,
+ ENGINE_ID_DIGE,
+ ENGINE_ID_DIGE
+};
+
+static enum engine_id dcn42_get_preferred_eng_id_dpia(unsigned int dpia_index)
+{
+ return dpia_to_preferred_enc_id_table[dpia_index];
+}
+
+static struct dce_i2c_hw *dcn42_i2c_hw_create(
+ struct dc_context *ctx,
+ uint32_t inst)
+{
+ struct dce_i2c_hw *dce_i2c_hw =
+ kzalloc(sizeof(struct dce_i2c_hw), GFP_KERNEL);
+
+ if (!dce_i2c_hw)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT i2c_hw_regs
+ i2c_inst_regs_init(1),
+ i2c_inst_regs_init(2),
+ i2c_inst_regs_init(3),
+ i2c_inst_regs_init(4),
+ i2c_inst_regs_init(5);
+ dcn2_i2c_hw_construct(dce_i2c_hw, ctx, inst,
+ &i2c_hw_regs[inst], &i2c_shifts, &i2c_masks);
+
+ return dce_i2c_hw;
+}
+
+static struct clock_source *dcn42_clock_source_create(
+ struct dc_context *ctx,
+ struct dc_bios *bios,
+ enum clock_source_id id,
+ const struct dce110_clk_src_regs *regs,
+ bool dp_clk_src)
+{
+ struct dce110_clk_src *clk_src =
+ kzalloc(sizeof(struct dce110_clk_src), GFP_KERNEL);
+
+ if (!clk_src)
+ return NULL;
+
+ if (dcn401_clk_src_construct(clk_src, ctx, bios, id,
+ regs, &cs_shift, &cs_mask)) {
+ clk_src->base.dp_clk_src = dp_clk_src;
+ return &clk_src->base;
+ }
+
+ kfree(clk_src);
+ BREAK_TO_DEBUGGER();
+ return NULL;
+}
+
+static struct hubbub *dcn42_hubbub_create(struct dc_context *ctx)
+{
+ int i;
+
+ struct dcn20_hubbub *hubbub3 = kzalloc(sizeof(struct dcn20_hubbub),
+ GFP_KERNEL);
+
+ if (!hubbub3)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT hubbub_reg
+ hubbub_reg_init();
+
+#undef REG_STRUCT
+#define REG_STRUCT vmid_regs
+ vmid_regs_init(0),
+ vmid_regs_init(1),
+ vmid_regs_init(2),
+ vmid_regs_init(3),
+ vmid_regs_init(4),
+ vmid_regs_init(5),
+ vmid_regs_init(6),
+ vmid_regs_init(7),
+ vmid_regs_init(8),
+ vmid_regs_init(9),
+ vmid_regs_init(10),
+ vmid_regs_init(11),
+ vmid_regs_init(12),
+ vmid_regs_init(13),
+ vmid_regs_init(14),
+ vmid_regs_init(15);
+
+ hubbub42_construct(hubbub3, ctx,
+ &hubbub_reg,
+ &hubbub_shift,
+ &hubbub_mask,
+ DCN42_DEFAULT_DET_SIZE,
+ 8,
+ DCN42_CRB_SIZE_KB);
+ for (i = 0; i < res_cap_dcn42.num_vmid; i++) {
+ struct dcn20_vmid *vmid = &hubbub3->vmid[i];
+
+ vmid->ctx = ctx;
+
+ vmid->regs = &vmid_regs[i];
+ vmid->shifts = &vmid_shifts;
+ vmid->masks = &vmid_masks;
+ }
+
+ return &hubbub3->base;
+}
+
+static struct hubp *dcn42_hubp_create(
+ struct dc_context *ctx,
+ uint32_t inst)
+{
+ struct dcn20_hubp *hubp2 =
+ kzalloc(sizeof(struct dcn20_hubp), GFP_KERNEL);
+
+ if (!hubp2)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT hubp_regs
+ hubp_regs_init(0),
+ hubp_regs_init(1),
+ hubp_regs_init(2),
+ hubp_regs_init(3);
+
+ if (hubp42_construct(hubp2, ctx, inst,
+ &hubp_regs[inst], &hubp_shift, &hubp_mask))
+ return &hubp2->base;
+
+ BREAK_TO_DEBUGGER();
+ kfree(hubp2);
+ return NULL;
+}
+static const struct dc_panel_config dcn42_panel_config_defaults = {
+ .psr = {
+ .disable_psr = false,
+ .disallow_psrsu = false,
+ .disallow_replay = false,
+ },
+ .ilr = {
+ .optimize_edp_link_rate = true,
+ },
+};
+
+static void dcn42_dpp_destroy(struct dpp **dpp)
+{
+ kfree(TO_DCN42_DPP(*dpp));
+ *dpp = NULL;
+}
+
+static struct dpp *dcn42_dpp_create(
+ struct dc_context *ctx,
+ uint32_t inst)
+{
+ struct dcn42_dpp *dpp42 =
+ kzalloc(sizeof(struct dcn42_dpp), GFP_KERNEL);
+
+ if (!dpp42)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT dpp_regs
+ dpp_regs_init(0),
+ dpp_regs_init(1),
+ dpp_regs_init(2),
+ dpp_regs_init(3);
+
+ if (dpp42_construct(dpp42, ctx, inst,
+ &dpp_regs[inst], &tf_shift, &tf_mask))
+ return &dpp42->base;
+
+ BREAK_TO_DEBUGGER();
+ kfree(dpp42);
+ return NULL;
+}
+
+static struct mpc *dcn42_mpc_create(
+ struct dc_context *ctx,
+ int num_mpcc,
+ int num_rmu)
+{
+ struct dcn42_mpc *mpc401 = kzalloc(sizeof(struct dcn42_mpc),
+ GFP_KERNEL);
+
+ if (!mpc401)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT mpc_regs
+ dcn_mpc_regs_init();
+
+ dcn42_mpc_construct(mpc401, ctx,
+ &mpc_regs,
+ &mpc_shift,
+ &mpc_mask,
+ num_mpcc,
+ num_rmu);
+
+ return &mpc401->base;
+}
+
+static struct output_pixel_processor *dcn42_opp_create(
+ struct dc_context *ctx, uint32_t inst)
+{
+ struct dcn20_opp *opp4 =
+ kzalloc(sizeof(struct dcn20_opp), GFP_KERNEL);
+
+ if (!opp4) {
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+
+#undef REG_STRUCT
+#define REG_STRUCT opp_regs
+ opp_regs_init(0),
+ opp_regs_init(1),
+ opp_regs_init(2),
+ opp_regs_init(3);
+ dcn20_opp_construct(opp4, ctx, inst,
+ &opp_regs[inst], &opp_shift, &opp_mask);
+ return &opp4->base;
+}
+
+static struct timing_generator *dcn42_timing_generator_create(
+ struct dc_context *ctx,
+ uint32_t instance)
+{
+ struct optc *tgn10 =
+ kzalloc(sizeof(struct optc), GFP_KERNEL);
+
+ if (!tgn10)
+ return NULL;
+#undef REG_STRUCT
+#define REG_STRUCT optc_regs
+ optc_regs_init(0),
+ optc_regs_init(1),
+ optc_regs_init(2),
+ optc_regs_init(3);
+ tgn10->base.inst = instance;
+ tgn10->base.ctx = ctx;
+
+ tgn10->tg_regs = &optc_regs[instance];
+ tgn10->tg_shift = &optc_shift;
+ tgn10->tg_mask = &optc_mask;
+
+ dcn42_timing_generator_init(tgn10);
+
+ return &tgn10->base;
+}
+
+static const struct encoder_feature_support link_enc_feature = {
+ .max_hdmi_deep_color = COLOR_DEPTH_121212,
+ .max_hdmi_pixel_clock = 600000,
+ .hdmi_ycbcr420_supported = true,
+ .dp_ycbcr420_supported = true,
+ .fec_supported = true,
+ .flags.bits.IS_HBR2_CAPABLE = true,
+ .flags.bits.IS_HBR3_CAPABLE = true,
+ .flags.bits.IS_TPS3_CAPABLE = true,
+ .flags.bits.IS_TPS4_CAPABLE = true};
+
+static struct link_encoder *dcn42_link_encoder_create(
+ struct dc_context *ctx,
+ const struct encoder_init_data *enc_init_data)
+{
+ struct dcn20_link_encoder *enc20 =
+ kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);
+
+ if (!enc20 || enc_init_data->hpd_source >= ARRAY_SIZE(link_enc_hpd_regs))
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT link_enc_aux_regs
+ aux_regs_init(0),
+ aux_regs_init(1),
+ aux_regs_init(2),
+ aux_regs_init(3),
+ aux_regs_init(4);
+#undef REG_STRUCT
+#define REG_STRUCT link_enc_hpd_regs
+ hpd_regs_init(0),
+ hpd_regs_init(1),
+ hpd_regs_init(2),
+ hpd_regs_init(3),
+ hpd_regs_init(4);
+#undef REG_STRUCT
+#define REG_STRUCT link_enc_regs
+ link_regs_init(0, A),
+ link_regs_init(1, B),
+ link_regs_init(2, C),
+ link_regs_init(3, D),
+ link_regs_init(4, E);
+
+ dcn42_link_encoder_construct(enc20,
+ enc_init_data,
+ &link_enc_feature,
+ &link_enc_regs[enc_init_data->transmitter],
+ &link_enc_aux_regs[enc_init_data->channel - 1],
+ &link_enc_hpd_regs[enc_init_data->hpd_source],
+ &le_shift,
+ &le_mask);
+ return &enc20->enc10.base;
+}
+
+static void read_dce_straps(
+ struct dc_context *ctx,
+ struct resource_straps *straps)
+{
+ generic_reg_get(ctx, regDC_PINSTRAPS + BASE(regDC_PINSTRAPS_BASE_IDX),
+ FN(DC_PINSTRAPS, DC_PINSTRAPS_AUDIO), &straps->dc_pinstraps_audio);
+}
+
+static struct audio *dcn42_create_audio(
+ struct dc_context *ctx, unsigned int inst)
+{
+
+#undef REG_STRUCT
+#define REG_STRUCT audio_regs
+ audio_regs_init(0),
+ audio_regs_init(1),
+ audio_regs_init(2),
+ audio_regs_init(3),
+ audio_regs_init(4);
+
+ return dce_audio_create(ctx, inst,
+ &audio_regs[inst], &audio_shift, &audio_mask);
+}
+
+static struct vpg *dcn42_vpg_create(
+ struct dc_context *ctx,
+ uint32_t inst)
+{
+ struct dcn31_vpg *vpg4 = kzalloc(sizeof(struct dcn31_vpg), GFP_KERNEL);
+
+ if (!vpg4)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT vpg_regs
+ vpg_regs_init(0),
+ vpg_regs_init(1),
+ vpg_regs_init(2),
+ vpg_regs_init(3),
+ vpg_regs_init(4),
+ vpg_regs_init(5),
+ vpg_regs_init(6),
+ vpg_regs_init(7),
+ vpg_regs_init(8),
+ vpg_regs_init(9);
+ vpg31_construct(vpg4, ctx, inst,
+ &vpg_regs[inst],
+ &vpg_shift,
+ &vpg_mask);
+
+ return &vpg4->base;
+}
+
+static struct apg *dcn42_apg_create(
+ struct dc_context *ctx,
+ uint32_t inst)
+{
+ struct dcn31_apg *apg31 = kzalloc(sizeof(struct dcn31_apg), GFP_KERNEL);
+
+ if (!apg31)
+ return NULL;
+
+#undef REG_STRUCT
+#define REG_STRUCT apg_regs
+ apg_regs_init(0),
+ apg_regs_init(1),
+ apg_regs_init(2),
+ apg_regs_init(3),
+ apg_regs_init(4),
+ apg_regs_init(5),
+ apg_regs_init(6),
+ apg_regs_init(7),
+ apg_regs_init(8),
+ apg_regs_init(9);
+
+ apg31_construct(apg31, ctx, inst,
+ &apg_regs[inst],
+ &apg_shift,
+ &apg_mask);
+
+ return &apg31->base;
+}
+
+static struct stream_encoder *dcn42_stream_encoder_create(
+ enum engine_id eng_id,
+ struct dc_context *ctx)
+{
+ struct dcn10_stream_encoder *enc1;
+ struct vpg *vpg;
+ struct apg *apg;
+
+ uint32_t vpg_inst;
+ uint32_t apg_inst;
+
+ /* Mapping of VPG, DME register blocks to DIO block instance */
+ if (eng_id <= ENGINE_ID_DIGE) {
+ vpg_inst = eng_id;
+ apg_inst = eng_id;
+ } else
+ return NULL;
+
+ enc1 = kzalloc(sizeof(struct dcn10_stream_encoder), GFP_KERNEL);
+ vpg = dcn42_vpg_create(ctx, vpg_inst);
+ apg = dcn42_apg_create(ctx, apg_inst);
+
+ if (!enc1 || !vpg || !apg) {
+ kfree(enc1);
+ kfree(vpg);
+ kfree(apg);
+ return NULL;
+ }
+#undef REG_STRUCT
+#define REG_STRUCT stream_enc_regs
+ stream_enc_regs_init(0),
+ stream_enc_regs_init(1),
+ stream_enc_regs_init(2),
+ stream_enc_regs_init(3),
+ stream_enc_regs_init(4);
+
+ dcn42_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios,
+ eng_id, vpg, apg,
+ &stream_enc_regs[eng_id],
+ &se_shift, &se_mask);
+ return &enc1->base;
+}
+
+static struct hpo_dp_stream_encoder *dcn42_hpo_dp_stream_encoder_create(
+ enum engine_id eng_id,
+ struct dc_context *ctx)
+{
+ struct dcn31_hpo_dp_stream_encoder *hpo_dp_enc31;
+ struct vpg *vpg;
+ struct apg *apg;
+ uint32_t hpo_dp_inst;
+ uint32_t vpg_inst;
+ uint32_t apg_inst;
+
+ ASSERT((eng_id >= ENGINE_ID_HPO_DP_0) && (eng_id <= ENGINE_ID_HPO_DP_3));
+ hpo_dp_inst = eng_id - ENGINE_ID_HPO_DP_0;
+
+ /* Mapping of VPG register blocks to HPO DP block instance:
+ * VPG[5] -> HPO_DP[0]
+ * VPG[6] -> HPO_DP[1]
+ * VPG[7] -> HPO_DP[2]
+ * VPG[8] -> HPO_DP[3]
+ */
+ vpg_inst = hpo_dp_inst + 5;
+
+ /* Mapping of APG register blocks to HPO DP block instance:
+ * APG[6] -> HPO_DP[0]
+ * APG[7] -> HPO_DP[1]
+ * APG[8] -> HPO_DP[2]
+ * APG[9] -> HPO_DP[3]
+ */
+ apg_inst = hpo_dp_inst + 5;
+
+ /* allocate HPO stream encoder and create VPG sub-block */
+ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_stream_encoder), GFP_KERNEL);
+ vpg = dcn42_vpg_create(ctx, vpg_inst);
+ apg = dcn42_apg_create(ctx, apg_inst);
+
+ if (!hpo_dp_enc31 || !vpg || !apg) {
+ kfree(hpo_dp_enc31);
+ kfree(vpg);
+ kfree(apg);
+ return NULL;
+ }
+
+#undef REG_STRUCT
+#define REG_STRUCT hpo_dp_stream_enc_regs
+ hpo_dp_stream_encoder_reg_init(0),
+ hpo_dp_stream_encoder_reg_init(1),
+ hpo_dp_stream_encoder_reg_init(2),
+ hpo_dp_stream_encoder_reg_init(3);
+
+ dcn31_hpo_dp_stream_encoder_construct(hpo_dp_enc31, ctx, ctx->dc_bios,
+ hpo_dp_inst, eng_id, vpg, apg,
+ &hpo_dp_stream_enc_regs[hpo_dp_inst],
+ &hpo_dp_se_shift, &hpo_dp_se_mask);
+
+ return &hpo_dp_enc31->base;
+}
+
+static struct hpo_dp_link_encoder *dcn42_hpo_dp_link_encoder_create(
+ uint8_t inst,
+ struct dc_context *ctx)
+{
+ struct dcn31_hpo_dp_link_encoder *hpo_dp_enc31;
+
+ /* allocate HPO link encoder */
+ hpo_dp_enc31 = kzalloc(sizeof(struct dcn31_hpo_dp_link_encoder), GFP_KERNEL);
+ if (!hpo_dp_enc31)
+ return NULL; /* out of memory */
+
+#undef REG_STRUCT
+#define REG_STRUCT hpo_dp_link_enc_regs
+ hpo_dp_link_encoder_reg_init(0),
+ hpo_dp_link_encoder_reg_init(1),
+ hpo_dp_link_encoder_reg_init(2),
+ hpo_dp_link_encoder_reg_init(3);
+
+ hpo_dp_link_encoder42_construct(hpo_dp_enc31, ctx, inst,
+ &hpo_dp_link_enc_regs[inst],
+ &hpo_dp_le_shift, &hpo_dp_le_mask);
+
+ return &hpo_dp_enc31->base;
+}
+
+static struct dce_hwseq *dcn42_hwseq_create(
+ struct dc_context *ctx)
+{
+ struct dce_hwseq *hws = kzalloc(sizeof(struct dce_hwseq), GFP_KERNEL);
+
+#undef REG_STRUCT
+#define REG_STRUCT hwseq_reg
+ hwseq_reg_init();
+
+ if (hws) {
+ hws->ctx = ctx;
+ hws->regs = &hwseq_reg;
+ hws->shifts = &hwseq_shift;
+ hws->masks = &hwseq_mask;
+ }
+
+ return hws;
+}
+
+static const struct resource_create_funcs res_create_funcs = {
+ .read_dce_straps = read_dce_straps,
+ .create_audio = dcn42_create_audio,
+ .create_stream_encoder = dcn42_stream_encoder_create,
+ .create_hpo_dp_stream_encoder = dcn42_hpo_dp_stream_encoder_create,
+ .create_hpo_dp_link_encoder = dcn42_hpo_dp_link_encoder_create,
+ .create_hwseq = dcn42_hwseq_create,
+};
+
+static void dcn42_dsc_destroy(struct display_stream_compressor **dsc)
+{
+ kfree(container_of(*dsc, struct dcn401_dsc, base));
+ *dsc = NULL;
+}
+
+static void dcn42_resource_destruct(struct dcn42_resource_pool *pool)
+{
+ unsigned int i;
+
+ for (i = 0; i < pool->base.stream_enc_count; i++) {
+ if (pool->base.stream_enc[i] != NULL) {
+ if (pool->base.stream_enc[i]->vpg != NULL) {
+ kfree(DCN31_VPG_FROM_VPG(pool->base.stream_enc[i]->vpg));
+ pool->base.stream_enc[i]->vpg = NULL;
+ }
+ if (pool->base.stream_enc[i]->apg != NULL) {
+ kfree(DCN31_APG_FROM_APG(pool->base.stream_enc[i]->apg));
+ pool->base.stream_enc[i]->apg = NULL;
+ }
+ kfree(DCN10STRENC_FROM_STRENC(pool->base.stream_enc[i]));
+ pool->base.stream_enc[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.hpo_dp_stream_enc_count; i++) {
+ if (pool->base.hpo_dp_stream_enc[i] != NULL) {
+ if (pool->base.hpo_dp_stream_enc[i]->vpg != NULL) {
+ kfree(DCN31_VPG_FROM_VPG(pool->base.hpo_dp_stream_enc[i]->vpg));
+ pool->base.hpo_dp_stream_enc[i]->vpg = NULL;
+ }
+ if (pool->base.hpo_dp_stream_enc[i]->apg != NULL) {
+ kfree(DCN31_APG_FROM_APG(pool->base.hpo_dp_stream_enc[i]->apg));
+ pool->base.hpo_dp_stream_enc[i]->apg = NULL;
+ }
+ kfree(DCN3_1_HPO_DP_STREAM_ENC_FROM_HPO_STREAM_ENC(pool->base.hpo_dp_stream_enc[i]));
+ pool->base.hpo_dp_stream_enc[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.hpo_dp_link_enc_count; i++) {
+ if (pool->base.hpo_dp_link_enc[i] != NULL) {
+ kfree(DCN3_1_HPO_DP_LINK_ENC_FROM_HPO_LINK_ENC(pool->base.hpo_dp_link_enc[i]));
+ pool->base.hpo_dp_link_enc[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
+ if (pool->base.dscs[i] != NULL)
+ dcn42_dsc_destroy(&pool->base.dscs[i]);
+ }
+
+ if (pool->base.mpc != NULL) {
+ kfree(TO_DCN20_MPC(pool->base.mpc));
+ pool->base.mpc = NULL;
+ }
+ if (pool->base.hubbub != NULL) {
+ kfree(TO_DCN20_HUBBUB(pool->base.hubbub));
+ pool->base.hubbub = NULL;
+ }
+ for (i = 0; i < pool->base.pipe_count; i++) {
+ if (pool->base.dpps[i] != NULL)
+ dcn42_dpp_destroy(&pool->base.dpps[i]);
+
+ if (pool->base.ipps[i] != NULL)
+ pool->base.ipps[i]->funcs->ipp_destroy(&pool->base.ipps[i]);
+
+ if (pool->base.hubps[i] != NULL) {
+ kfree(TO_DCN20_HUBP(pool->base.hubps[i]));
+ pool->base.hubps[i] = NULL;
+ }
+
+ if (pool->base.irqs != NULL)
+ dal_irq_service_destroy(&pool->base.irqs);
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
+ if (pool->base.engines[i] != NULL)
+ dce110_engine_destroy(&pool->base.engines[i]);
+ if (pool->base.hw_i2cs[i] != NULL) {
+ kfree(pool->base.hw_i2cs[i]);
+ pool->base.hw_i2cs[i] = NULL;
+ }
+ if (pool->base.sw_i2cs[i] != NULL) {
+ kfree(pool->base.sw_i2cs[i]);
+ pool->base.sw_i2cs[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_opp; i++) {
+ if (pool->base.opps[i] != NULL)
+ pool->base.opps[i]->funcs->opp_destroy(&pool->base.opps[i]);
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
+ if (pool->base.timing_generators[i] != NULL) {
+ kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i]));
+ pool->base.timing_generators[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_dwb; i++) {
+ if (pool->base.dwbc[i] != NULL) {
+ kfree(TO_DCN30_DWBC(pool->base.dwbc[i]));
+ pool->base.dwbc[i] = NULL;
+ }
+ if (pool->base.mcif_wb[i] != NULL) {
+ kfree(TO_DCN30_MMHUBBUB(pool->base.mcif_wb[i]));
+ pool->base.mcif_wb[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.audio_count; i++) {
+ if (pool->base.audios[i])
+ dce_aud_destroy(&pool->base.audios[i]);
+ }
+
+ for (i = 0; i < pool->base.clk_src_count; i++) {
+ if (pool->base.clock_sources[i] != NULL) {
+ dcn20_clock_source_destroy(&pool->base.clock_sources[i]);
+ pool->base.clock_sources[i] = NULL;
+ }
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_mpc_3dlut; i++) {
+ if (pool->base.mpc_lut[i] != NULL) {
+ dc_3dlut_func_release(pool->base.mpc_lut[i]);
+ pool->base.mpc_lut[i] = NULL;
+ }
+ if (pool->base.mpc_shaper[i] != NULL) {
+ dc_transfer_func_release(pool->base.mpc_shaper[i]);
+ pool->base.mpc_shaper[i] = NULL;
+ }
+ }
+
+ if (pool->base.dp_clock_source != NULL) {
+ dcn20_clock_source_destroy(&pool->base.dp_clock_source);
+ pool->base.dp_clock_source = NULL;
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_timing_generator; i++) {
+ if (pool->base.multiple_abms[i] != NULL)
+ dce_abm_destroy(&pool->base.multiple_abms[i]);
+ }
+
+ if (pool->base.psr != NULL)
+ dmub_psr_destroy(&pool->base.psr);
+
+ if (pool->base.pg_cntl != NULL)
+ dcn_pg_cntl_destroy(&pool->base.pg_cntl);
+ if (pool->base.dccg != NULL)
+ dcn_dccg_destroy(&pool->base.dccg);
+
+ if (pool->base.oem_device != NULL) {
+ struct dc *dc = pool->base.oem_device->ctx->dc;
+
+ dc->link_srv->destroy_ddc_service(&pool->base.oem_device);
+ }
+}
+
+static void dcn42_build_pipe_pix_clk_params(struct pipe_ctx *pipe_ctx)
+{
+ const struct dc_stream_state *stream = pipe_ctx->stream;
+ struct dc_link *link = stream->link;
+ struct link_encoder *link_enc = pipe_ctx->link_res.dio_link_enc;
+ struct pixel_clk_params *pixel_clk_params = &pipe_ctx->stream_res.pix_clk_params;
+
+ pixel_clk_params->requested_pix_clk_100hz = stream->timing.pix_clk_100hz;
+
+ if (pipe_ctx->dsc_padding_params.dsc_hactive_padding != 0)
+ pixel_clk_params->requested_pix_clk_100hz = pipe_ctx->dsc_padding_params.dsc_pix_clk_100hz;
+
+ if (!pipe_ctx->stream->ctx->dc->config.unify_link_enc_assignment)
+ link_enc = link_enc_cfg_get_link_enc(link);
+ if (link_enc)
+ pixel_clk_params->encoder_object_id = link_enc->id;
+
+ pixel_clk_params->signal_type = pipe_ctx->stream->signal;
+ pixel_clk_params->controller_id = pipe_ctx->stream_res.tg->inst + 1;
+ /* TODO: un-hardcode*/
+
+ /* TODO - DP2.0 HW: calculate requested_sym_clk for UHBR rates */
+
+ pixel_clk_params->requested_sym_clk = LINK_RATE_LOW *
+ LINK_RATE_REF_FREQ_IN_KHZ;
+ pixel_clk_params->flags.ENABLE_SS = 0;
+ pixel_clk_params->color_depth =
+ stream->timing.display_color_depth;
+ pixel_clk_params->flags.DISPLAY_BLANKED = 1;
+ pixel_clk_params->pixel_encoding = stream->timing.pixel_encoding;
+
+ if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422)
+ pixel_clk_params->color_depth = COLOR_DEPTH_888;
+
+ if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
+ pixel_clk_params->requested_pix_clk_100hz *= 2;
+ if (dc_is_tmds_signal(stream->signal) &&
+ stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
+ pixel_clk_params->requested_pix_clk_100hz /= 2;
+
+ pipe_ctx->clock_source->funcs->get_pix_clk_dividers(
+ pipe_ctx->clock_source,
+ &pipe_ctx->stream_res.pix_clk_params,
+ &pipe_ctx->pll_settings);
+
+ pixel_clk_params->dio_se_pix_per_cycle = 1;
+ if (dc_is_tmds_signal(stream->signal) &&
+ stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
+ pixel_clk_params->dio_se_pix_per_cycle = 2;
+ } else if (dc_is_dp_signal(stream->signal)) {
+ /* round up to nearest power of 2, or max at 8 pixels per cycle */
+ if (pixel_clk_params->requested_pix_clk_100hz > 4 * stream->ctx->dc->clk_mgr->dprefclk_khz * 10) {
+ pixel_clk_params->dio_se_pix_per_cycle = 8;
+ } else if (pixel_clk_params->requested_pix_clk_100hz > 2 * stream->ctx->dc->clk_mgr->dprefclk_khz * 10) {
+ pixel_clk_params->dio_se_pix_per_cycle = 4;
+ } else if (pixel_clk_params->requested_pix_clk_100hz > stream->ctx->dc->clk_mgr->dprefclk_khz * 10) {
+ pixel_clk_params->dio_se_pix_per_cycle = 2;
+ } else {
+ pixel_clk_params->dio_se_pix_per_cycle = 1;
+ }
+ }
+}
+
+static bool dcn42_dwbc_create(struct dc_context *ctx, struct resource_pool *pool)
+{
+ int i;
+ uint32_t dwb_count = pool->res_cap->num_dwb;
+
+ for (i = 0; i < dwb_count; i++) {
+ struct dcn30_dwbc *dwbc42 = kzalloc(sizeof(struct dcn30_dwbc),
+ GFP_KERNEL);
+
+ if (!dwbc42) {
+ dm_error("DC: failed to create dwbc42!\n");
+ return false;
+ }
+
+#undef REG_STRUCT
+#define REG_STRUCT dwbc401_regs
+ dwbc_regs_dcn401_init(0);
+
+ dcn30_dwbc_construct(dwbc42, ctx,
+ &dwbc401_regs[i],
+ &dwbc401_shift,
+ &dwbc401_mask,
+ i);
+
+ pool->dwbc[i] = &dwbc42->base;
+ }
+ return true;
+}
+
+static void dcn42_mmhubbub_init(struct dcn30_mmhubbub *mcif_wb30,
+ struct dc_context *ctx)
+{
+ dcn42_mmhubbub_set_fgcg(
+ mcif_wb30,
+ ctx->dc->debug.enable_fine_grain_clock_gating.bits.mmhubbub);
+}
+
+static bool dcn42_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool)
+{
+ int i;
+ uint32_t pipe_count = pool->res_cap->num_dwb;
+
+ for (i = 0; i < pipe_count; i++) {
+ struct dcn30_mmhubbub *mcif_wb30 = kzalloc(sizeof(struct dcn30_mmhubbub),
+ GFP_KERNEL);
+
+ if (!mcif_wb30) {
+ dm_error("DC: failed to create mcif_wb30!\n");
+ return false;
+ }
+
+#undef REG_STRUCT
+#define REG_STRUCT mcif_wb35_regs
+ mcif_wb_regs_dcn3_init(0);
+
+ dcn35_mmhubbub_construct(mcif_wb30, ctx,
+ &mcif_wb35_regs[i],
+ &mcif_wb35_shift,
+ &mcif_wb35_mask,
+ i);
+
+ dcn42_mmhubbub_init(mcif_wb30, ctx);
+
+ pool->mcif_wb[i] = &mcif_wb30->base;
+ }
+ return true;
+}
+
+static struct display_stream_compressor *dcn42_dsc_create(
+ struct dc_context *ctx, uint32_t inst)
+{
+ struct dcn401_dsc *dsc =
+ kzalloc(sizeof(struct dcn401_dsc), GFP_KERNEL);
+
+ if (!dsc) {
+ BREAK_TO_DEBUGGER();
+ return NULL;
+ }
+
+#undef REG_STRUCT
+#define REG_STRUCT dsc_regs
+ dsc_regs_init(0),
+ dsc_regs_init(1),
+ dsc_regs_init(2),
+ dsc_regs_init(3);
+
+ dsc401_construct(dsc, ctx, inst, &dsc_regs[inst], &dsc_shift, &dsc_mask);
+ dsc401_set_fgcg(dsc, ctx->dc->debug.enable_fine_grain_clock_gating.bits.dsc);
+
+ dsc->max_image_width = 5760;
+
+ return &dsc->base;
+}
+
+static void dcn42_destroy_resource_pool(struct resource_pool **pool)
+{
+ struct dcn42_resource_pool *dcn42_pool = TO_DCN42_RES_POOL(*pool);
+
+ dcn42_resource_destruct(dcn42_pool);
+ kfree(dcn42_pool);
+ *pool = NULL;
+}
+
+static struct dc_cap_funcs cap_funcs = {
+ .get_dcc_compression_cap = dcn20_get_dcc_compression_cap};
+
+static void dcn42_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params)
+{
+ (void)bw_params;
+ dc_assert_fp_enabled();
+
+ if (dc->current_state && dc->current_state->bw_ctx.dml2)
+ dml2_reinit(dc, &dc->dml2_options, &dc->current_state->bw_ctx.dml2);
+}
+
+static void dcn42_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
+{
+ DC_FP_START();
+ dcn42_update_bw_bounding_box_fpu(dc, bw_params);
+ DC_FP_END();
+}
+enum dc_status dcn42_validate_bandwidth(struct dc *dc,
+ struct dc_state *context,
+ enum dc_validate_mode validate_mode)
+{
+ bool out = false;
+
+ DC_FP_START();
+
+ out = dml2_validate(dc, context, context->bw_ctx.dml2,
+ validate_mode);
+
+ if (validate_mode == DC_VALIDATE_MODE_AND_PROGRAMMING) {
+ /*not required for mode enumeration*/
+ dcn42_decide_zstate_support(dc, context);
+ }
+
+ DC_FP_END();
+
+ return out ? DC_OK : DC_FAIL_BANDWIDTH_VALIDATE;
+}
+void dcn42_prepare_mcache_programming(struct dc *dc,
+ struct dc_state *context)
+{
+ if (dc->debug.using_dml21) {
+ DC_FP_START();
+ dml2_prepare_mcache_programming(dc, context,
+ context->power_source == DC_POWER_SOURCE_DC ?
+ context->bw_ctx.dml2_dc_power_source : context->bw_ctx.dml2);
+ DC_FP_END();
+ }
+}
+/* Create a minimal link encoder object not associated with a particular
+ * physical connector.
+ * resource_funcs.link_enc_create_minimal
+ */
+static struct link_encoder *dcn42_link_enc_create_minimal(
+ struct dc_context *ctx, enum engine_id eng_id)
+{
+ struct dcn20_link_encoder *enc20;
+
+ if ((eng_id - ENGINE_ID_DIGA) > ctx->dc->res_pool->res_cap->num_dig_link_enc)
+ return NULL;
+
+ enc20 = kzalloc(sizeof(struct dcn20_link_encoder), GFP_KERNEL);
+ if (!enc20)
+ return NULL;
+
+ dcn31_link_encoder_construct_minimal(
+ enc20,
+ ctx,
+ &link_enc_feature,
+ &link_enc_regs[eng_id - ENGINE_ID_DIGA],
+ eng_id);
+
+ return &enc20->enc10.base;
+}
+static void dcn42_get_panel_config_defaults(struct dc_panel_config *panel_config)
+{
+ *panel_config = dcn42_panel_config_defaults;
+}
+static unsigned int dcn42_get_max_hw_cursor_size(const struct dc *dc,
+ struct dc_state *state,
+ const struct dc_stream_state *stream)
+{
+ (void)state;
+ (void)stream;
+ return dc->caps.max_cursor_size;
+}
+static struct resource_funcs dcn42_res_pool_funcs = {
+ .destroy = dcn42_destroy_resource_pool,
+ .link_enc_create = dcn42_link_encoder_create,
+ .link_enc_create_minimal = dcn42_link_enc_create_minimal,
+ .link_encs_assign = link_enc_cfg_link_encs_assign,
+ .link_enc_unassign = link_enc_cfg_link_enc_unassign,
+ .panel_cntl_create = dcn32_panel_cntl_create,
+ .validate_bandwidth = dcn42_validate_bandwidth,
+ .calculate_wm_and_dlg = NULL,
+ .populate_dml_pipes = NULL,
+ .acquire_free_pipe_as_secondary_dpp_pipe = dcn32_acquire_free_pipe_as_secondary_dpp_pipe,
+ .acquire_free_pipe_as_secondary_opp_head = dcn32_acquire_free_pipe_as_secondary_opp_head,
+ .release_pipe = dcn20_release_pipe,
+ .add_stream_to_ctx = dcn30_add_stream_to_ctx,
+ .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource,
+ .remove_stream_from_ctx = dcn20_remove_stream_from_ctx,
+ .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context,
+ .set_mcif_arb_params = dcn30_set_mcif_arb_params,
+ .find_first_free_match_stream_enc_for_link = dcn10_find_first_free_match_stream_enc_for_link,
+ .acquire_post_bldn_3dlut = dcn32_acquire_post_bldn_3dlut,
+ .release_post_bldn_3dlut = dcn32_release_post_bldn_3dlut,
+ .update_bw_bounding_box = dcn42_update_bw_bounding_box,
+ .patch_unknown_plane_state = dcn35_patch_unknown_plane_state,
+ .get_panel_config_defaults = dcn42_get_panel_config_defaults,
+ .get_preferred_eng_id_dpia = dcn42_get_preferred_eng_id_dpia,
+ .update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
+ .add_phantom_pipes = dcn32_add_phantom_pipes,
+ .calculate_mall_ways_from_bytes = dcn32_calculate_mall_ways_from_bytes,
+ .prepare_mcache_programming = dcn42_prepare_mcache_programming,
+ .build_pipe_pix_clk_params = dcn42_build_pipe_pix_clk_params,
+ .get_power_profile = dcn401_get_power_profile,
+ .get_vstartup_for_pipe = dcn401_get_vstartup_for_pipe,
+ .get_max_hw_cursor_size = dcn42_get_max_hw_cursor_size,
+ .get_default_tiling_info = dcn10_get_default_tiling_info
+};
+
+static uint32_t read_pipe_fuses(struct dc_context *ctx)
+{
+ uint32_t value = REG_READ(CC_DC_PIPE_DIS);
+
+ if (value == 0 && ctx->dce_environment == DCE_ENV_DIAG)
+ value = 0xF;
+ /* DCN401 support max 4 pipes */
+ value = value & 0xf;
+ return value;
+}
+
+static bool dcn42_resource_construct(
+ uint8_t num_virtual_links,
+ struct dc *dc,
+ struct dcn42_resource_pool *pool)
+{
+ int i, j;
+ struct dc_context *ctx = dc->ctx;
+ struct irq_service_init_data init_data;
+ uint32_t pipe_fuses;
+ uint32_t num_pipes;
+
+#undef REG_STRUCT
+#define REG_STRUCT bios_regs
+ bios_regs_init();
+
+#undef REG_STRUCT
+#define REG_STRUCT clk_src_regs
+ clk_src_regs_init(0, A),
+ clk_src_regs_init(1, B),
+ clk_src_regs_init(2, C),
+ clk_src_regs_init(3, D),
+ clk_src_regs_init(4, E);
+
+#undef REG_STRUCT
+#define REG_STRUCT abm_regs
+ abm_regs_init(0),
+ abm_regs_init(1),
+ abm_regs_init(2),
+ abm_regs_init(3);
+#undef REG_STRUCT
+#define REG_STRUCT dccg_regs
+ dccg_regs_init();
+
+ ctx->dc_bios->regs = &bios_regs;
+
+ pool->base.res_cap = &res_cap_dcn42;
+
+ /* max number of pipes for ASIC before checking for pipe fuses */
+ num_pipes = pool->base.res_cap->num_dpp;
+ pipe_fuses = read_pipe_fuses(ctx);
+
+ for (i = 0; i < pool->base.res_cap->num_dpp; i++)
+ if (pipe_fuses & 1 << i)
+ num_pipes--;
+
+ if (pipe_fuses & 1)
+ ASSERT(0); // Unexpected - Pipe 0 should always be fully functional!
+
+ if (pipe_fuses & CC_DC_PIPE_DIS__DC_FULL_DIS_MASK)
+ ASSERT(0); // Entire DCN is harvested!
+
+ pool->base.funcs = &dcn42_res_pool_funcs;
+
+ /*************************************************
+ * Resource + asic cap harcoding *
+ *************************************************/
+ pool->base.underlay_pipe_index = (unsigned int)NO_UNDERLAY_PIPE;
+ pool->base.timing_generator_count = pool->base.res_cap->num_timing_generator;
+ pool->base.pipe_count = num_pipes;
+ pool->base.mpcc_count = num_pipes;
+ dc->caps.ips_v2_support = true;
+ dc->caps.max_downscale_ratio = 600;
+ dc->caps.i2c_speed_in_khz = 100;
+ dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a applied by default*/
+ /* TODO: Bring max cursor size back to 256 after subvp cursor corruption is fixed*/
+ dc->caps.max_cursor_size = 64;
+ dc->caps.max_buffered_cursor_size = 64;
+ dc->caps.cursor_not_scaled = true;
+ dc->caps.min_horizontal_blanking_period = 80;
+ dc->caps.dmdata_alloc_size = 2048;
+ dc->caps.mall_size_per_mem_channel = 4;
+ /* total size = mall per channel * num channels * 1024 * 1024 */
+ dc->caps.mall_size_total = dc->caps.mall_size_per_mem_channel *
+ dc->ctx->dc_bios->vram_info.num_chans * 1048576;
+ dc->caps.cursor_cache_size = dc->caps.max_cursor_size * dc->caps.max_cursor_size * 8;
+ dc->caps.cache_line_size = 64;
+ dc->caps.cache_num_ways = 16;
+
+ /* Calculate the available MALL space */
+ dc->caps.max_cab_allocation_bytes =
+ dcn32_calc_num_avail_chans_for_mall(dc, dc->ctx->dc_bios->vram_info.num_chans) *
+ dc->caps.mall_size_per_mem_channel * 1024 * 1024;
+ dc->caps.mall_size_total = dc->caps.max_cab_allocation_bytes;
+
+ dc->caps.subvp_fw_processing_delay_us = 15;
+ dc->caps.subvp_drr_max_vblank_margin_us = 40;
+ dc->caps.subvp_prefetch_end_to_mall_start_us = 15;
+ dc->caps.subvp_swath_height_margin_lines = 16;
+ dc->caps.subvp_pstate_allow_width_us = 20;
+ dc->caps.subvp_vertical_int_margin_us = 30;
+ dc->caps.subvp_drr_vblank_start_margin_us = 100; // 100us margin
+
+ dc->caps.max_slave_planes = 2;
+ dc->caps.max_slave_yuv_planes = 2;
+ dc->caps.max_slave_rgb_planes = 2;
+ dc->caps.post_blend_color_processing = true;
+ dc->caps.force_dp_tps4_for_cp2520 = true;
+ if (dc->config.forceHBR2CP2520)
+ dc->caps.force_dp_tps4_for_cp2520 = false;
+ dc->caps.dp_hdmi21_pcon_support = true;
+ dc->caps.dp_hpo = true;
+ dc->caps.edp_dsc_support = true;
+ dc->caps.extended_aux_timeout_support = true;
+ dc->caps.dmcub_support = true;
+ dc->caps.is_apu = true;
+ dc->caps.seamless_odm = true;
+ dc->caps.zstate_support = true;
+ dc->caps.ips_support = true;
+ dc->caps.max_v_total = (1 << 15) - 1;
+ dc->caps.vtotal_limited_by_fp2 = true;
+
+ dc->caps.seamless_odm = true;
+ dc->caps.zstate_support = true;
+ dc->caps.ips_support = true;
+ dc->caps.max_v_total = (1 << 15) - 1;
+ dc->caps.vtotal_limited_by_fp2 = true;
+
+ /* Color pipeline capabilities */
+ dc->caps.color.dpp.dcn_arch = 1;
+ dc->caps.color.dpp.input_lut_shared = 0;
+ dc->caps.color.dpp.icsc = 1;
+ dc->caps.color.dpp.dgam_ram = 0; // must use gamma_corr
+ dc->caps.color.dpp.dgam_rom_caps.srgb = 1;
+ dc->caps.color.dpp.dgam_rom_caps.bt2020 = 1;
+ dc->caps.color.dpp.dgam_rom_caps.gamma2_2 = 1;
+ dc->caps.color.dpp.dgam_rom_caps.pq = 1;
+ dc->caps.color.dpp.dgam_rom_caps.hlg = 1;
+ dc->caps.color.dpp.post_csc = 1;
+ dc->caps.color.dpp.gamma_corr = 1;
+ dc->caps.color.dpp.dgam_rom_for_yuv = 0;
+
+ dc->caps.color.dpp.hw_3d_lut = 0;
+ dc->caps.color.dpp.ogam_ram = 0;
+ // no OGAM ROM on DCN2 and later ASICs
+ dc->caps.color.dpp.ogam_rom_caps.srgb = 0;
+ dc->caps.color.dpp.ogam_rom_caps.bt2020 = 0;
+ dc->caps.color.dpp.ogam_rom_caps.gamma2_2 = 0;
+ dc->caps.color.dpp.ogam_rom_caps.pq = 0;
+ dc->caps.color.dpp.ogam_rom_caps.hlg = 0;
+ dc->caps.color.dpp.ocsc = 0;
+
+ dc->caps.color.mpc.gamut_remap = 1;
+ //configurable to be before or after BLND in MPCC
+ dc->caps.color.mpc.num_3dluts = pool->base.res_cap->num_mpc_3dlut;
+ dc->caps.color.mpc.num_rmcm_3dluts = 2;
+ dc->caps.color.mpc.ogam_ram = 1;
+ dc->caps.color.mpc.ogam_rom_caps.srgb = 0;
+ dc->caps.color.mpc.ogam_rom_caps.bt2020 = 0;
+ dc->caps.color.mpc.ogam_rom_caps.gamma2_2 = 0;
+ dc->caps.color.mpc.ogam_rom_caps.pq = 0;
+ dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
+ dc->caps.color.mpc.ocsc = 1;
+ dc->caps.color.mpc.preblend = true;
+ dc->caps.color.mpc.mcm_3d_lut_caps.dma_3d_lut = 1;
+ dc->caps.color.mpc.mcm_3d_lut_caps.lut_dim_caps.dim_9 = 1;
+ dc->caps.color.mpc.mcm_3d_lut_caps.lut_dim_caps.dim_17 = 1;
+ dc->caps.color.mpc.mcm_3d_lut_caps.mem_layout_support.linear_1d = 1;
+ dc->caps.color.mpc.mcm_3d_lut_caps.mem_layout_support.swizzle_3d_bgr = 1;
+ dc->caps.color.mpc.mcm_3d_lut_caps.mem_layout_support.swizzle_3d_rgb = 1;
+ dc->caps.color.mpc.mcm_3d_lut_caps.mem_format_support.unorm_12msb = 1;
+ dc->caps.color.mpc.mcm_3d_lut_caps.mem_format_support.unorm_12lsb = 1;
+ dc->caps.color.mpc.mcm_3d_lut_caps.mem_format_support.float_fp1_5_10 = 1;
+ dc->caps.color.mpc.mcm_3d_lut_caps.mem_pixel_order_support.order_rgba = 1;
+ dc->caps.color.mpc.mcm_3d_lut_caps.mem_pixel_order_support.order_bgra = 1;
+ dc->caps.color.mpc.rmcm_3d_lut_caps.dma_3d_lut = 1;
+ dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_17 = 1;
+ dc->caps.color.mpc.rmcm_3d_lut_caps.lut_dim_caps.dim_33 = 1;
+ dc->caps.color.mpc.rmcm_3d_lut_caps.mem_layout_support.linear_1d = 1;
+ dc->caps.color.mpc.rmcm_3d_lut_caps.mem_layout_support.swizzle_3d_bgr = 1;
+ dc->caps.color.mpc.rmcm_3d_lut_caps.mem_layout_support.swizzle_3d_rgb = 1;
+ dc->caps.color.mpc.rmcm_3d_lut_caps.mem_format_support.unorm_12msb = 1;
+ dc->caps.color.mpc.rmcm_3d_lut_caps.mem_format_support.unorm_12lsb = 1;
+ dc->caps.color.mpc.rmcm_3d_lut_caps.mem_format_support.float_fp1_5_10 = 1;
+ dc->caps.color.mpc.rmcm_3d_lut_caps.mem_pixel_order_support.order_rgba = 1;
+ dc->caps.color.mpc.rmcm_3d_lut_caps.mem_pixel_order_support.order_bgra = 1;
+
+ dc->caps.num_of_host_routers = 3;
+ dc->caps.num_of_dpias_per_host_router = 2;
+
+ /* max_disp_clock_khz_at_vmin is slightly lower than the STA value in order
+ * to provide some margin.
+ * It's expected for furture ASIC to have equal or higher value, in order to
+ * have determinstic power improvement from generate to genration.
+ * (i.e., we should not expect new ASIC generation with lower vmin rate)
+ */
+ dc->caps.max_disp_clock_khz_at_vmin = 650000;
+ dc->config.use_spl = true;
+ dc->config.prefer_easf = true;
+
+ dc->config.dcn_sharpness_range.sdr_rgb_min = 0;
+ dc->config.dcn_sharpness_range.sdr_rgb_max = 1750;
+ dc->config.dcn_sharpness_range.sdr_rgb_mid = 750;
+ dc->config.dcn_sharpness_range.sdr_yuv_min = 0;
+ dc->config.dcn_sharpness_range.sdr_yuv_max = 3500;
+ dc->config.dcn_sharpness_range.sdr_yuv_mid = 1500;
+ dc->config.dcn_sharpness_range.hdr_rgb_min = 0;
+ dc->config.dcn_sharpness_range.hdr_rgb_max = 2750;
+ dc->config.dcn_sharpness_range.hdr_rgb_mid = 1500;
+
+ dc->config.dcn_override_sharpness_range.sdr_rgb_min = 0;
+ dc->config.dcn_override_sharpness_range.sdr_rgb_max = 3250;
+ dc->config.dcn_override_sharpness_range.sdr_rgb_mid = 1250;
+ dc->config.dcn_override_sharpness_range.sdr_yuv_min = 0;
+ dc->config.dcn_override_sharpness_range.sdr_yuv_max = 3500;
+ dc->config.dcn_override_sharpness_range.sdr_yuv_mid = 1500;
+ dc->config.dcn_override_sharpness_range.hdr_rgb_min = 0;
+ dc->config.dcn_override_sharpness_range.hdr_rgb_max = 2750;
+ dc->config.dcn_override_sharpness_range.hdr_rgb_mid = 1500;
+
+ dc->config.use_pipe_ctx_sync_logic = true;
+ dc->config.dc_mode_clk_limit_support = false;
+ dc->config.enable_windowed_mpo_odm = true;
+ /* Use psp mailbox to enable assr */
+ dc->config.use_assr_psp_message = true;
+ /* dcn42 and afterward always support external panel replay */
+ dc->config.frame_update_cmd_version2 = true;
+
+ /* read VBIOS LTTPR caps */
+ {
+ if (ctx->dc_bios->funcs->get_lttpr_caps) {
+ enum bp_result bp_query_result;
+ uint8_t is_vbios_lttpr_enable = 0;
+
+ bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable);
+ dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable;
+ }
+
+ dc->caps.vbios_lttpr_aware = true;
+ }
+ dc->check_config = config_defaults;
+
+ if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
+ dc->debug = debug_defaults_drv;
+
+ /*HW default is to have all the FGCG enabled, SW no need to program them*/
+ dc->debug.enable_fine_grain_clock_gating.u32All = 0xFFFF;
+ // Init the vm_helper
+ if (dc->vm_helper)
+ vm_helper_init(dc->vm_helper, 16);
+
+ /*************************************************
+ * Create resources *
+ *************************************************/
+
+ /* Clock Sources for Pixel Clock*/
+ pool->base.clock_sources[DCN401_CLK_SRC_PLL0] =
+ dcn42_clock_source_create(ctx, ctx->dc_bios,
+ CLOCK_SOURCE_COMBO_PHY_PLL0,
+ &clk_src_regs[0], false);
+ pool->base.clock_sources[DCN401_CLK_SRC_PLL1] =
+ dcn42_clock_source_create(ctx, ctx->dc_bios,
+ CLOCK_SOURCE_COMBO_PHY_PLL1,
+ &clk_src_regs[1], false);
+ pool->base.clock_sources[DCN401_CLK_SRC_PLL2] =
+ dcn42_clock_source_create(ctx, ctx->dc_bios,
+ CLOCK_SOURCE_COMBO_PHY_PLL2,
+ &clk_src_regs[2], false);
+ pool->base.clock_sources[DCN401_CLK_SRC_PLL3] =
+ dcn42_clock_source_create(ctx, ctx->dc_bios,
+ CLOCK_SOURCE_COMBO_PHY_PLL3,
+ &clk_src_regs[3], false);
+ pool->base.clock_sources[DCN401_CLK_SRC_PLL4] =
+ dcn42_clock_source_create(ctx, ctx->dc_bios,
+ CLOCK_SOURCE_COMBO_PHY_PLL4,
+ &clk_src_regs[4], false);
+
+ pool->base.clk_src_count = DCN401_CLK_SRC_TOTAL;
+
+ /* todo: not reuse phy_pll registers */
+ pool->base.dp_clock_source =
+ dcn42_clock_source_create(ctx, ctx->dc_bios,
+ CLOCK_SOURCE_ID_DP_DTO,
+ &clk_src_regs[0], true);
+
+ for (i = 0; i < pool->base.clk_src_count; i++) {
+ if (pool->base.clock_sources[i] == NULL) {
+ dm_error("DC: failed to create clock sources!\n");
+ BREAK_TO_DEBUGGER();
+ goto create_fail;
+ }
+ }
+
+ /* DCCG */
+ pool->base.dccg = dccg42_create(ctx, &dccg_regs, &dccg_shift, &dccg_mask);
+ if (pool->base.dccg == NULL) {
+ dm_error("DC: failed to create dccg!\n");
+ BREAK_TO_DEBUGGER();
+ goto create_fail;
+ }
+
+#undef REG_STRUCT
+#define REG_STRUCT pg_cntl_regs
+ pg_cntl_dcn42_regs_init();
+
+ pool->base.pg_cntl = pg_cntl42_create(ctx, &pg_cntl_regs, &pg_cntl_shift, &pg_cntl_mask);
+ if (pool->base.pg_cntl == NULL) {
+ dm_error("DC: failed to create power gate control!\n");
+ BREAK_TO_DEBUGGER();
+ goto create_fail;
+ }
+ /* IRQ Service */
+ init_data.ctx = dc->ctx;
+ pool->base.irqs = dal_irq_service_dcn42_create(&init_data);
+ if (!pool->base.irqs)
+ goto create_fail;
+
+ /* HUBBUB */
+ pool->base.hubbub = dcn42_hubbub_create(ctx);
+ if (pool->base.hubbub == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create hubbub!\n");
+ goto create_fail;
+ }
+
+ /* HUBPs, DPPs, OPPs, TGs, ABMs */
+ for (i = 0, j = 0; i < pool->base.res_cap->num_timing_generator; i++) {
+ /* if pipe is disabled, skip instance of HW pipe,
+ * i.e, skip ASIC register instance
+ */
+ if (pipe_fuses & 1 << i)
+ continue;
+
+ pool->base.hubps[j] = dcn42_hubp_create(ctx, i);
+ if (pool->base.hubps[j] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error(
+ "DC: failed to create hubps!\n");
+ goto create_fail;
+ }
+
+ pool->base.dpps[j] = dcn42_dpp_create(ctx, i);
+ if (pool->base.dpps[j] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error(
+ "DC: failed to create dpps!\n");
+ goto create_fail;
+ }
+
+ pool->base.opps[j] = dcn42_opp_create(ctx, i);
+ if (pool->base.opps[j] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error(
+ "DC: failed to create output pixel processor!\n");
+ goto create_fail;
+ }
+
+ pool->base.timing_generators[j] = dcn42_timing_generator_create(
+ ctx, i);
+ if (pool->base.timing_generators[j] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create tg!\n");
+ goto create_fail;
+ }
+
+ pool->base.multiple_abms[j] = dmub_abm_create(ctx,
+ &abm_regs[i],
+ &abm_shift,
+ &abm_mask);
+ if (pool->base.multiple_abms[j] == NULL) {
+ dm_error("DC: failed to create abm for pipe %d!\n", i);
+ BREAK_TO_DEBUGGER();
+ goto create_fail;
+ }
+
+ /* index for resource pool arrays for next valid pipe */
+ j++;
+ }
+
+ /* PSR */
+ pool->base.psr = dmub_psr_create(ctx);
+ if (pool->base.psr == NULL) {
+ dm_error("DC: failed to create psr obj!\n");
+ BREAK_TO_DEBUGGER();
+ goto create_fail;
+ }
+
+ /* Replay */
+ pool->base.replay = dmub_replay_create(ctx);
+ if (pool->base.replay == NULL) {
+ dm_error("DC: failed to create replay obj!\n");
+ BREAK_TO_DEBUGGER();
+ goto create_fail;
+ }
+
+ /* MPCCs */
+ pool->base.mpc = dcn42_mpc_create(ctx, pool->base.res_cap->num_timing_generator,
+ pool->base.res_cap->num_mpc_3dlut);
+ if (pool->base.mpc == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create mpc!\n");
+ goto create_fail;
+ }
+
+ /* DSCs */
+ for (i = 0; i < pool->base.res_cap->num_dsc; i++) {
+ pool->base.dscs[i] = dcn42_dsc_create(ctx, i);
+ if (pool->base.dscs[i] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create display stream compressor %d!\n", i);
+ goto create_fail;
+ }
+ }
+
+ /* DWB */
+ if (!dcn42_dwbc_create(ctx, &pool->base)) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create dwbc!\n");
+ goto create_fail;
+ }
+
+ /* MMHUBBUB */
+ if (!dcn42_mmhubbub_create(ctx, &pool->base)) {
+ BREAK_TO_DEBUGGER();
+ dm_error("DC: failed to create mcif_wb!\n");
+ goto create_fail;
+ }
+
+ /* AUX and I2C */
+ for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
+ pool->base.engines[i] = dcn42_aux_engine_create(ctx, i);
+
+ if (pool->base.engines[i] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error(
+ "DC:failed to create aux engine!!\n");
+ goto create_fail;
+ }
+ pool->base.hw_i2cs[i] = dcn42_i2c_hw_create(ctx, i);
+ if (pool->base.hw_i2cs[i] == NULL) {
+ BREAK_TO_DEBUGGER();
+ dm_error(
+ "DC:failed to create hw i2c!!\n");
+ goto create_fail;
+ }
+ pool->base.sw_i2cs[i] = NULL;
+ }
+ /* DCN4.2 has 6 DPIA */
+ pool->base.usb4_dpia_count = dc->caps.num_of_host_routers * dc->caps.num_of_dpias_per_host_router;
+ if (dc->debug.dpia_debug.bits.disable_dpia)
+ pool->base.usb4_dpia_count = 0;
+
+ /* Audio, HWSeq, Stream Encoders including HPO and virtual, MPC 3D LUTs */
+ if (!resource_construct(num_virtual_links, dc, &pool->base,
+ &res_create_funcs))
+ goto create_fail;
+
+ /* HW Sequencer init functions and Plane caps */
+ dcn42_hw_sequencer_init_functions(dc);
+
+ dc->caps.max_planes = pool->base.pipe_count;
+
+ for (i = 0; i < dc->caps.max_planes; ++i)
+ dc->caps.planes[i] = plane_cap;
+
+ dc->caps.max_odm_combine_factor = 4;
+
+ dc->cap_funcs = cap_funcs;
+ dc->dcn_ip->max_num_dpp = pool->base.pipe_count;
+
+ // For now enable SDPIF_REQUEST_RATE_LIMIT on DCN4_01 when vram_info.num_chans provided
+ if (dc->config.sdpif_request_limit_words_per_umc == 0)
+ dc->config.sdpif_request_limit_words_per_umc = 16;
+
+ dc->dml2_options.dcn_pipe_count = pool->base.pipe_count;
+ /*this will use real soc clock table*/
+ dc->dml2_options.use_native_soc_bb_construction = true;
+ dc->dml2_options.minimize_dispclk_using_odm = false;
+ if (dc->config.EnableMinDispClkODM)
+ dc->dml2_options.minimize_dispclk_using_odm = true;
+ dc->dml2_options.enable_windowed_mpo_odm = dc->config.enable_windowed_mpo_odm;
+ dc->dml2_options.map_dc_pipes_with_callbacks = true;
+ dc->dml2_options.force_tdlut_enable = true;
+
+ resource_init_common_dml2_callbacks(dc, &dc->dml2_options);
+ dc->dml2_options.callbacks.can_support_mclk_switch_using_fw_based_vblank_stretch =
+ &dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch;
+ dc->dml2_options.svp_pstate.callbacks.release_dsc = &dcn20_release_dsc;
+ dc->dml2_options.svp_pstate.callbacks.calculate_mall_ways_from_bytes =
+ pool->base.funcs->calculate_mall_ways_from_bytes;
+
+ dc->dml2_options.svp_pstate.subvp_fw_processing_delay_us = dc->caps.subvp_fw_processing_delay_us;
+ dc->dml2_options.svp_pstate.subvp_prefetch_end_to_mall_start_us = dc->caps.subvp_prefetch_end_to_mall_start_us;
+ dc->dml2_options.svp_pstate.subvp_pstate_allow_width_us = dc->caps.subvp_pstate_allow_width_us;
+ dc->dml2_options.svp_pstate.subvp_swath_height_margin_lines = dc->caps.subvp_swath_height_margin_lines;
+
+ dc->dml2_options.svp_pstate.force_disable_subvp = dc->debug.force_disable_subvp;
+ dc->dml2_options.svp_pstate.force_enable_subvp = dc->debug.force_subvp_mclk_switch;
+
+ dc->dml2_options.mall_cfg.cache_line_size_bytes = dc->caps.cache_line_size;
+ dc->dml2_options.mall_cfg.cache_num_ways = dc->caps.cache_num_ways;
+ dc->dml2_options.mall_cfg.max_cab_allocation_bytes =
+ dc->caps.max_cab_allocation_bytes;
+ dc->dml2_options.mall_cfg.mblk_height_4bpe_pixels = DCN3_2_MBLK_HEIGHT_4BPE;
+ dc->dml2_options.mall_cfg.mblk_height_8bpe_pixels = DCN3_2_MBLK_HEIGHT_8BPE;
+ dc->dml2_options.mall_cfg.mblk_size_bytes = DCN3_2_MALL_MBLK_SIZE_BYTES;
+ dc->dml2_options.mall_cfg.mblk_width_pixels = DCN3_2_MBLK_WIDTH;
+
+ dc->dml2_options.max_segments_per_hubp = 24;
+ dc->dml2_options.det_segment_size = DCN42_CRB_SEGMENT_SIZE_KB;
+ dc->dml2_options.gpuvm_enable = true;
+ dc->dml2_options.hostvm_enable = true;
+
+ /* SPL */
+ dc->caps.scl_caps.sharpener_support = true;
+
+ return true;
+
+create_fail:
+
+ dcn42_resource_destruct(pool);
+
+ return false;
+}
+struct resource_pool *dcn42_create_resource_pool(
+ const struct dc_init_data *init_data,
+ struct dc *dc)
+{
+ struct dcn42_resource_pool *pool =
+ kzalloc(sizeof(struct dcn401_resource_pool), GFP_KERNEL);
+
+ if (!pool)
+ return NULL;
+
+ if (dcn42_resource_construct(init_data->num_virtual_links, dc, pool))
+ return &pool->base;
+
+ BREAK_TO_DEBUGGER();
+ kfree(pool);
+ return NULL;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h
new file mode 100644
index 000000000000..60acf0e423d9
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource.h
@@ -0,0 +1,591 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef _DCN42_RESOURCE_H_
+#define _DCN42_RESOURCE_H_
+
+#include "core_types.h"
+
+#define TO_DCN42_RES_POOL(pool) \
+ container_of(pool, struct dcn42_resource_pool, base)
+
+/* DPP */
+#define DPP_REG_LIST_DCN42_COMMON_RI(id) \
+ SRI_ARR(CM_DEALPHA, CM, id), SRI_ARR(CM_MEM_PWR_STATUS, CM, id), \
+ SRI_ARR(CM_BIAS_CR_R, CM, id), SRI_ARR(CM_BIAS_Y_G_CB_B, CM, id), \
+ SRI_ARR(PRE_DEGAM, CNVC_CFG, id), SRI_ARR(CM_GAMCOR_CONTROL, CM, id), \
+ SRI_ARR(CM_GAMCOR_LUT_CONTROL, CM, id), \
+ SRI_ARR(CM_GAMCOR_LUT_INDEX, CM, id), \
+ SRI_ARR(CM_GAMCOR_LUT_INDEX, CM, id), \
+ SRI_ARR(CM_GAMCOR_LUT_DATA, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_B, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_G, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_START_CNTL_R, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_B, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_G, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_START_SLOPE_CNTL_R, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_B, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_B, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_G, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_G, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_END_CNTL1_R, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_END_CNTL2_R, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_REGION_0_1, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_REGION_32_33, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_OFFSET_B, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_OFFSET_G, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_OFFSET_R, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_B, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_G, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMB_START_BASE_CNTL_R, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_B, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_G, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_START_CNTL_R, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_B, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_G, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_START_SLOPE_CNTL_R, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_B, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_B, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_G, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_G, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_END_CNTL1_R, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_END_CNTL2_R, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_REGION_0_1, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_REGION_32_33, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_OFFSET_B, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_OFFSET_G, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_OFFSET_R, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_B, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_G, CM, id), \
+ SRI_ARR(CM_GAMCOR_RAMA_START_BASE_CNTL_R, CM, id), \
+ SRI_ARR(CM_HIST_CNTL, CM, id), \
+ SRI_ARR(CM_HIST_LOCK, CM, id), \
+ SRI_ARR(CM_HIST_INDEX, CM, id), \
+ SRI_ARR(CM_HIST_DATA, CM, id), \
+ SRI_ARR(CM_HIST_STATUS, CM, id), \
+ SRI_ARR(CM_HIST_SCALE_SRC1, CM, id), \
+ SRI_ARR(CM_HIST_COEFA_SRC2, CM, id), \
+ SRI_ARR(CM_HIST_COEFB_SRC2, CM, id), \
+ SRI_ARR(CM_HIST_COEFC_SRC2, CM, id), \
+ SRI_ARR(CM_HIST_SCALE_SRC3, CM, id), \
+ SRI_ARR(CM_HIST_BIAS_SRC1, CM, id), \
+ SRI_ARR(CM_HIST_BIAS_SRC2, CM, id), \
+ SRI_ARR(CM_HIST_BIAS_SRC3, CM, id), \
+ SRI_ARR(DSCL_EXT_OVERSCAN_LEFT_RIGHT, DSCL, id), \
+ SRI_ARR(DSCL_EXT_OVERSCAN_TOP_BOTTOM, DSCL, id), \
+ SRI_ARR(OTG_H_BLANK, DSCL, id), SRI_ARR(OTG_V_BLANK, DSCL, id), \
+ SRI_ARR(SCL_MODE, DSCL, id), SRI_ARR(LB_DATA_FORMAT, DSCL, id), \
+ SRI_ARR(LB_MEMORY_CTRL, DSCL, id), SRI_ARR(DSCL_AUTOCAL, DSCL, id), \
+ SRI_ARR(SCL_TAP_CONTROL, DSCL, id), \
+ SRI_ARR(SCL_COEF_RAM_TAP_SELECT, DSCL, id), \
+ SRI_ARR(SCL_COEF_RAM_TAP_DATA, DSCL, id), \
+ SRI_ARR(DSCL_2TAP_CONTROL, DSCL, id), SRI_ARR(MPC_SIZE, DSCL, id), \
+ SRI_ARR(SCL_HORZ_FILTER_SCALE_RATIO, DSCL, id), \
+ SRI_ARR(SCL_VERT_FILTER_SCALE_RATIO, DSCL, id), \
+ SRI_ARR(SCL_HORZ_FILTER_SCALE_RATIO_C, DSCL, id), \
+ SRI_ARR(SCL_VERT_FILTER_SCALE_RATIO_C, DSCL, id), \
+ SRI_ARR(SCL_HORZ_FILTER_INIT, DSCL, id), \
+ SRI_ARR(SCL_HORZ_FILTER_INIT_C, DSCL, id), \
+ SRI_ARR(SCL_VERT_FILTER_INIT, DSCL, id), \
+ SRI_ARR(SCL_VERT_FILTER_INIT_C, DSCL, id), \
+ SRI_ARR(RECOUT_START, DSCL, id), SRI_ARR(RECOUT_SIZE, DSCL, id), \
+ SRI_ARR(PRE_DEALPHA, CNVC_CFG, id), SRI_ARR(PRE_REALPHA, CNVC_CFG, id), \
+ SRI_ARR(PRE_CSC_MODE, CNVC_CFG, id), \
+ SRI_ARR(PRE_CSC_C11_C12, CNVC_CFG, id), \
+ SRI_ARR(PRE_CSC_C33_C34, CNVC_CFG, id), \
+ SRI_ARR(PRE_CSC_B_C11_C12, CNVC_CFG, id), \
+ SRI_ARR(PRE_CSC_B_C33_C34, CNVC_CFG, id), \
+ SRI_ARR(CM_POST_CSC_CONTROL, CM, id), \
+ SRI_ARR(CM_POST_CSC_C11_C12, CM, id), \
+ SRI_ARR(CM_POST_CSC_C33_C34, CM, id), \
+ SRI_ARR(CM_POST_CSC_B_C11_C12, CM, id), \
+ SRI_ARR(CM_POST_CSC_B_C33_C34, CM, id), \
+ SRI_ARR(CM_MEM_PWR_CTRL, CM, id), SRI_ARR(CM_CONTROL, CM, id), \
+ SRI_ARR(CM_TEST_DEBUG_INDEX, CM, id), \
+ SRI_ARR(CM_TEST_DEBUG_DATA, CM, id), \
+ SRI_ARR(FORMAT_CONTROL, CNVC_CFG, id), \
+ SRI_ARR(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \
+ SRI_ARR(CURSOR0_CONTROL, CM_CUR, id), \
+ SRI_ARR(CURSOR0_COLOR0, CM_CUR, id), \
+ SRI_ARR(CURSOR0_COLOR1, CM_CUR, id), \
+ SRI_ARR(CURSOR0_FP_SCALE_BIAS_G_Y, CM_CUR, id), \
+ SRI_ARR(CURSOR0_FP_SCALE_BIAS_RB_CRCB, CM_CUR, id), \
+ SRI_ARR(CUR0_MATRIX_MODE, CM_CUR, id), \
+ SRI_ARR(CUR0_MATRIX_C11_C12_A, CM_CUR, id), \
+ SRI_ARR(CUR0_MATRIX_C13_C14_A, CM_CUR, id), \
+ SRI_ARR(CUR0_MATRIX_C21_C22_A, CM_CUR, id), \
+ SRI_ARR(CUR0_MATRIX_C23_C24_A, CM_CUR, id), \
+ SRI_ARR(CUR0_MATRIX_C31_C32_A, CM_CUR, id), \
+ SRI_ARR(CUR0_MATRIX_C33_C34_A, CM_CUR, id), \
+ SRI_ARR(CUR0_MATRIX_C11_C12_B, CM_CUR, id), \
+ SRI_ARR(CUR0_MATRIX_C13_C14_B, CM_CUR, id), \
+ SRI_ARR(CUR0_MATRIX_C21_C22_B, CM_CUR, id), \
+ SRI_ARR(CUR0_MATRIX_C23_C24_B, CM_CUR, id), \
+ SRI_ARR(CUR0_MATRIX_C31_C32_B, CM_CUR, id), \
+ SRI_ARR(CUR0_MATRIX_C33_C34_B, CM_CUR, id), \
+ SRI_ARR(DPP_CONTROL, DPP_TOP, id), SRI_ARR(CM_HDR_MULT_COEF, CM, id), \
+ SRI_ARR(CURSOR_CONTROL, CURSOR0_, id), \
+ SRI_ARR(ALPHA_2BIT_LUT01, CNVC_CFG, id), \
+ SRI_ARR(ALPHA_2BIT_LUT23, CNVC_CFG, id), \
+ SRI_ARR(FCNV_FP_BIAS_R, CNVC_CFG, id), \
+ SRI_ARR(FCNV_FP_BIAS_G, CNVC_CFG, id), \
+ SRI_ARR(FCNV_FP_BIAS_B, CNVC_CFG, id), \
+ SRI_ARR(FCNV_FP_SCALE_R, CNVC_CFG, id), \
+ SRI_ARR(FCNV_FP_SCALE_G, CNVC_CFG, id), \
+ SRI_ARR(FCNV_FP_SCALE_B, CNVC_CFG, id), \
+ SRI_ARR(COLOR_KEYER_CONTROL, CNVC_CFG, id), \
+ SRI_ARR(COLOR_KEYER_ALPHA, CNVC_CFG, id), \
+ SRI_ARR(COLOR_KEYER_RED, CNVC_CFG, id), \
+ SRI_ARR(COLOR_KEYER_GREEN, CNVC_CFG, id), \
+ SRI_ARR(COLOR_KEYER_BLUE, CNVC_CFG, id), \
+ SRI_ARR(OBUF_MEM_PWR_CTRL, DSCL, id), \
+ SRI_ARR(DSCL_MEM_PWR_STATUS, DSCL, id), \
+ SRI_ARR(DSCL_MEM_PWR_CTRL, DSCL, id), \
+ SRI_ARR(DSCL_CONTROL, DSCL, id), \
+ SRI_ARR(DSCL_SC_MODE, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_MODE, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF_CNTL, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_RINGEST_EVENTAP_REDUCE, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_RINGEST_EVENTAP_GAIN, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF_FINAL_MAX_MIN, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG0, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG1, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG2, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG3, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG4, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG5, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG6, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF1_PWL_SEG7, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG0, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG1, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG2, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG3, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG4, DSCL, id), \
+ SRI_ARR(DSCL_EASF_H_BF3_PWL_SEG5, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_MODE, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF_CNTL, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_RINGEST_3TAP_CNTL1, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_RINGEST_3TAP_CNTL2, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_RINGEST_3TAP_CNTL3, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_RINGEST_EVENTAP_REDUCE, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_RINGEST_EVENTAP_GAIN, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF_FINAL_MAX_MIN, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG0, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG1, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG2, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG3, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG4, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG5, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG6, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF1_PWL_SEG7, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG0, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG1, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG2, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG3, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG4, DSCL, id), \
+ SRI_ARR(DSCL_EASF_V_BF3_PWL_SEG5, DSCL, id), \
+ SRI_ARR(DSCL_SC_MATRIX_C0C1, DSCL, id), \
+ SRI_ARR(DSCL_SC_MATRIX_C2C3, DSCL, id), \
+ SRI_ARR(ISHARP_MODE, DSCL, id), \
+ SRI_ARR(ISHARP_DELTA_LUT_MEM_PWR_CTRL, DSCL, id), \
+ SRI_ARR(ISHARP_NOISEDET_THRESHOLD, DSCL, id), \
+ SRI_ARR(ISHARP_NOISE_GAIN_PWL, DSCL, id), \
+ SRI_ARR(ISHARP_LBA_PWL_SEG0, DSCL, id), \
+ SRI_ARR(ISHARP_LBA_PWL_SEG1, DSCL, id), \
+ SRI_ARR(ISHARP_LBA_PWL_SEG2, DSCL, id), \
+ SRI_ARR(ISHARP_LBA_PWL_SEG3, DSCL, id), \
+ SRI_ARR(ISHARP_LBA_PWL_SEG4, DSCL, id), \
+ SRI_ARR(ISHARP_LBA_PWL_SEG5, DSCL, id), \
+ SRI_ARR(ISHARP_DELTA_CTRL, DSCL, id), \
+ SRI_ARR(ISHARP_DELTA_DATA, DSCL, id), \
+ SRI_ARR(ISHARP_DELTA_INDEX, DSCL, id), \
+ SRI_ARR(ISHARP_NLDELTA_SOFT_CLIP, DSCL, id), \
+ SRI_ARR(SCL_VERT_FILTER_INIT_BOT, DSCL, id), \
+ SRI_ARR(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id)
+
+/* Stream encoder */
+#define SE_DCN42_REG_LIST_RI(id) \
+ SRI_ARR(HDMI_CONTROL, DIG, id), SRI_ARR(HDMI_DB_CONTROL, DIG, id), \
+ SRI_ARR(HDMI_GC, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL2, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL3, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL4, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL5, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL6, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL7, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL8, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL9, DIG, id), \
+ SRI_ARR(HDMI_GENERIC_PACKET_CONTROL10, DIG, id), \
+ SRI_ARR(HDMI_INFOFRAME_CONTROL0, DIG, id), \
+ SRI_ARR(HDMI_VBI_PACKET_CONTROL, DIG, id), \
+ SRI_ARR(HDMI_AUDIO_PACKET_CONTROL, DIG, id), \
+ SRI_ARR(HDMI_ACR_PACKET_CONTROL, DIG, id), \
+ SRI_ARR(HDMI_ACR_32_0, DIG, id), SRI_ARR(HDMI_ACR_32_1, DIG, id), \
+ SRI_ARR(HDMI_ACR_44_0, DIG, id), SRI_ARR(HDMI_ACR_44_1, DIG, id), \
+ SRI_ARR(HDMI_ACR_48_0, DIG, id), SRI_ARR(HDMI_ACR_48_1, DIG, id), \
+ SRI_ARR(DP_DB_CNTL, DP, id), SRI_ARR(DP_MSA_MISC, DP, id), \
+ SRI_ARR(DP_MSA_VBID_MISC, DP, id), SRI_ARR(DP_MSA_COLORIMETRY, DP, id), \
+ SRI_ARR(DP_MSA_TIMING_PARAM1, DP, id), \
+ SRI_ARR(DP_MSA_TIMING_PARAM2, DP, id), \
+ SRI_ARR(DP_MSA_TIMING_PARAM3, DP, id), \
+ SRI_ARR(DP_MSA_TIMING_PARAM4, DP, id), \
+ SRI_ARR(DP_MSE_RATE_CNTL, DP, id), SRI_ARR(DP_MSE_RATE_UPDATE, DP, id), \
+ SRI_ARR(DP_PIXEL_FORMAT, DP, id), SRI_ARR(DP_SEC_CNTL, DP, id), \
+ SRI_ARR(DP_SEC_CNTL1, DP, id), SRI_ARR(DP_SEC_CNTL2, DP, id), \
+ SRI_ARR(DP_SEC_CNTL5, DP, id), SRI_ARR(DP_SEC_CNTL6, DP, id), \
+ SRI_ARR(DP_STEER_FIFO, DP, id), SRI_ARR(DP_VID_M, DP, id), \
+ SRI_ARR(DP_VID_N, DP, id), SRI_ARR(DP_VID_STREAM_CNTL, DP, id), \
+ SRI_ARR(DP_VID_TIMING, DP, id), SRI_ARR(DP_SEC_AUD_N, DP, id), \
+ SRI_ARR(DP_SEC_TIMESTAMP, DP, id), \
+ SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \
+ SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \
+ SRI_ARR(DP_SEC_FRAMING4, DP, id), SRI_ARR(DP_GSP11_CNTL, DP, id), \
+ SRI_ARR(DME_CONTROL, DME, id), \
+ SRI_ARR(DP_SEC_METADATA_TRANSMISSION, DP, id), \
+ SRI_ARR(HDMI_METADATA_PACKET_CONTROL, DIG, id), \
+ SRI_ARR(DIG_FE_CNTL, DIG, id), \
+ SRI_ARR(DIG_FE_EN_CNTL, DIG, id), \
+ SRI_ARR(DIG_FE_CLK_CNTL, DIG, id), \
+ SRI_ARR(DIG_CLOCK_PATTERN, DIG, id), \
+ SRI_ARR(DIG_FIFO_CTRL0, DIG, id), \
+ SRI_ARR(STREAM_MAPPER_CONTROL, DIG, id),\
+ SRI_ARR(DIG_FE_AUDIO_CNTL, DIG, id)
+
+/* HPO DP stream encoder */
+#define DCN42_HPO_DP_STREAM_ENC_REG_LIST_RI(id) \
+ SR_ARR(DP_STREAM_MAPPER_CONTROL0, id), \
+ SR_ARR(DP_STREAM_MAPPER_CONTROL1, id), \
+ SR_ARR(DP_STREAM_MAPPER_CONTROL2, id), \
+ SR_ARR(DP_STREAM_MAPPER_CONTROL3, id), \
+ SRI_ARR(DP_STREAM_ENC_CLOCK_CONTROL, DP_STREAM_ENC, id), \
+ SRI_ARR(DP_STREAM_ENC_INPUT_MUX_CONTROL, DP_STREAM_ENC, id), \
+ SRI_ARR(DP_STREAM_ENC_AUDIO_CONTROL, DP_STREAM_ENC, id), \
+ SRI_ARR(DP_STREAM_ENC_CLOCK_RAMP_ADJUSTER_FIFO_STATUS_CONTROL0, DP_STREAM_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_CONTROL, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_PIXEL_FORMAT, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_PIXEL_FORMAT_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_MSA0, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_MSA1, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_MSA2, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_MSA3, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_MSA4, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_MSA5, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_MSA6, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_MSA7, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_MSA8, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_MSA_CONTROL, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_MSA_DOUBLE_BUFFER_CONTROL, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_FIFO_CONTROL, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_STREAM_CONTROL, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_VBID_CONTROL, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_SDP_CONTROL, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL0, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL2, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL3, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL5, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_SDP_GSP_CONTROL11, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_SDP_METADATA_PACKET_CONTROL, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_SDP_AUDIO_CONTROL0, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_VID_CRC_CONTROL, DP_SYM32_ENC, id), \
+ SRI_ARR(DP_SYM32_ENC_HBLANK_CONTROL, DP_SYM32_ENC, id)
+
+/*HPO DP link encoder regs */
+#define DCN42_HPO_DP_LINK_ENC_REG_LIST_RI(id) \
+ SRI_ARR(DP_LINK_ENC_CLOCK_CONTROL, DP_LINK_ENC, id), \
+ SRI_ARR(DP_DPHY_SYM32_CONTROL, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_STATUS, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_CONFIG, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED0, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED1, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED2, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_PRBS_SEED3, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_SQ_PULSE, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM0, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM1, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM2, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM3, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM4, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM5, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM6, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM7, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM8, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM9, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_TP_CUSTOM10, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_SAT_VC0, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_SAT_VC1, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_SAT_VC2, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_SAT_VC3, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL0, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL1, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL2, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_VC_RATE_CNTL3, DP_DPHY_SYM32, id), \
+ SRI_ARR(DP_DPHY_SYM32_SAT_UPDATE, DP_DPHY_SYM32, id)
+
+#define VPG_DCN42_REG_LIST_RI(id) \
+ SRI(VPG_GENERIC_STATUS, VPG, id), \
+ SRI(VPG_GENERIC_PACKET_ACCESS_CTRL, VPG, id), \
+ SRI(VPG_GENERIC_PACKET_DATA, VPG, id), \
+ SRI(VPG_GSP_FRAME_UPDATE_CTRL, VPG, id), \
+ SRI(VPG_GSP_IMMEDIATE_UPDATE_CTRL, VPG, id), \
+ SRI(VPG_MEM_PWR, VPG, id)
+
+/* DCCG */
+#define DCCG_REG_LIST_DCN42_RI() \
+ SR(DPPCLK_DTO_CTRL), \
+ DCCG_SRII(DTO_PARAM, DPPCLK, 0), \
+ DCCG_SRII(DTO_PARAM, DPPCLK, 1), \
+ DCCG_SRII(DTO_PARAM, DPPCLK, 2), \
+ DCCG_SRII(DTO_PARAM, DPPCLK, 3), \
+ DCCG_SRII(CLOCK_CNTL, HDMICHARCLK, 0), \
+ SR(HDMISTREAMCLK0_DTO_PARAM),\
+ SR(DCCG_GLOBAL_FGCG_REP_CNTL),\
+ SR(DISPCLK_FREQ_CHANGE_CNTL), \
+ SR(PHYASYMCLK_CLOCK_CNTL), \
+ SR(PHYBSYMCLK_CLOCK_CNTL), \
+ SR(PHYCSYMCLK_CLOCK_CNTL), \
+ SR(PHYDSYMCLK_CLOCK_CNTL), \
+ SR(PHYESYMCLK_CLOCK_CNTL), \
+ SR(DPSTREAMCLK_CNTL), \
+ SR(HDMISTREAMCLK_CNTL), \
+ SR(SYMCLK32_SE_CNTL), \
+ SR(SYMCLK32_LE_CNTL), \
+ DCCG_SRII(PIXEL_RATE_CNTL, OTG, 0), \
+ DCCG_SRII(PIXEL_RATE_CNTL, OTG, 1), \
+ DCCG_SRII(PIXEL_RATE_CNTL, OTG, 2), \
+ DCCG_SRII(PIXEL_RATE_CNTL, OTG, 3), \
+ SR(OTG_PIXEL_RATE_DIV), \
+ SR(DTBCLK_P_CNTL), \
+ SR(DCCG_AUDIO_DTO_SOURCE), \
+ SR(DENTIST_DISPCLK_CNTL), \
+ SR(DPPCLK_CTRL), \
+ DCCG_SRII(MODULO, DP_DTO, 0), \
+ DCCG_SRII(MODULO, DP_DTO, 1), \
+ DCCG_SRII(MODULO, DP_DTO, 2), \
+ DCCG_SRII(MODULO, DP_DTO, 3), \
+ DCCG_SRII(PHASE, DP_DTO, 0), \
+ DCCG_SRII(PHASE, DP_DTO, 1), \
+ DCCG_SRII(PHASE, DP_DTO, 2), \
+ DCCG_SRII(PHASE, DP_DTO, 3), \
+ SR(OTG_ADD_DROP_PIXEL_CNTL), \
+ SR(DSCCLK0_DTO_PARAM), \
+ SR(DSCCLK1_DTO_PARAM), \
+ SR(DSCCLK2_DTO_PARAM), \
+ SR(DSCCLK3_DTO_PARAM), \
+ SR(DSCCLK_DTO_CTRL), \
+ SR(DCCG_GATE_DISABLE_CNTL), \
+ SR(DCCG_GATE_DISABLE_CNTL2), \
+ SR(DCCG_GATE_DISABLE_CNTL3), \
+ SR(DCCG_GATE_DISABLE_CNTL4), \
+ SR(DCCG_GATE_DISABLE_CNTL5), \
+ SR(DCCG_GATE_DISABLE_CNTL6), \
+ SR(SYMCLKA_CLOCK_ENABLE), \
+ SR(SYMCLKB_CLOCK_ENABLE), \
+ SR(SYMCLKC_CLOCK_ENABLE), \
+ SR(SYMCLKD_CLOCK_ENABLE), \
+ SR(SYMCLKE_CLOCK_ENABLE)
+
+#define DCN42_AUD_COMMON_MASK_SH_LIST(mask_sh) \
+ SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh), \
+ SF(AZF0ENDPOINT0_AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh),\
+ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\
+ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\
+ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_USE_512FBR_DTO, mask_sh),\
+ SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO1_USE_512FBR_DTO, mask_sh),\
+ SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\
+ SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\
+ SF(DCCG_AUDIO_DTO1_MODULE, DCCG_AUDIO_DTO1_MODULE, mask_sh),\
+ SF(DCCG_AUDIO_DTO1_PHASE, DCCG_AUDIO_DTO1_PHASE, mask_sh),\
+ SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES, mask_sh),\
+ SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, CLKSTOP, mask_sh),\
+ SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, EPSS, mask_sh)
+
+ /* HPO FRL stream encoder */
+#define DCN42_HPO_FRL_STREAM_ENC_REG_LIST_RI(id) \
+ DCN3_0_HPO_FRL_STREAM_ENC_REG_LIST_RI(id), \
+ SR_ARR(HDMI_STREAM_ENC_AUDIO_CONTROL, id),\
+ SR_ARR(HDMI_TB_ENC_MEM_CTRL, id),\
+ SR_ARR(HDMI_FRL_ENC_MEM_CTRL, id)
+/* OPTC */
+#define OPTC_COMMON_REG_LIST_DCN42_RI(inst) \
+ SRI_ARR(OTG_VSTARTUP_PARAM, OTG, inst), \
+ SRI_ARR(OTG_VUPDATE_PARAM, OTG, inst), \
+ SRI_ARR(OTG_VREADY_PARAM, OTG, inst), \
+ SRI_ARR(OTG_MASTER_UPDATE_LOCK, OTG, inst), \
+ SRI_ARR(OTG_MASTER_UPDATE_MODE, OTG, inst), \
+ SRI_ARR(OTG_V_COUNT_STOP_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_V_COUNT_STOP_CONTROL2, OTG, inst), \
+ SRI_ARR(OTG_GSL_CONTROL, OTG, inst), \
+ SRI2_ARR(OPTC_CLOCK_CONTROL, OPTC, inst),\
+ SRI_ARR(OTG_GLOBAL_CONTROL0, OTG, inst), \
+ SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst), \
+ SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst), \
+ SRI_ARR(OTG_GLOBAL_CONTROL4, OTG, inst), \
+ SRI_ARR(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_H_TOTAL, OTG, inst), \
+ SRI_ARR(OTG_H_BLANK_START_END, OTG, inst), \
+ SRI_ARR(OTG_H_SYNC_A, OTG, inst),\
+ SRI_ARR(OTG_H_SYNC_A_CNTL, OTG, inst), \
+ SRI_ARR(OTG_H_TIMING_CNTL, OTG, inst), \
+ SRI_ARR(OTG_V_TOTAL, OTG, inst), \
+ SRI_ARR(OTG_V_BLANK_START_END, OTG, inst), \
+ SRI_ARR(OTG_V_SYNC_A, OTG, inst), \
+ SRI_ARR(OTG_V_SYNC_A_CNTL, OTG, inst), \
+ SRI_ARR(OTG_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_STEREO_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_3D_STRUCTURE_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_STEREO_STATUS, OTG, inst), \
+ SRI_ARR(OTG_V_TOTAL_MAX, OTG, inst), \
+ SRI_ARR(OTG_V_TOTAL_MIN, OTG, inst), \
+ SRI_ARR(OTG_V_TOTAL_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_TRIGA_CNTL, OTG, inst), \
+ SRI_ARR(OTG_FORCE_COUNT_NOW_CNTL, OTG, inst), \
+ SRI_ARR(OTG_STATIC_SCREEN_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_STATUS_FRAME_COUNT, OTG, inst), \
+ SRI_ARR(OTG_STATUS, OTG, inst), \
+ SRI_ARR(OTG_STATUS_POSITION, OTG, inst), \
+ SRI_ARR(OTG_NOM_VERT_POSITION, OTG, inst), \
+ SRI_ARR(OTG_M_CONST_DTO0, OTG, inst), \
+ SRI_ARR(OTG_M_CONST_DTO1, OTG, inst), \
+ SRI_ARR(OTG_CLOCK_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_VERTICAL_INTERRUPT0_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_VERTICAL_INTERRUPT0_POSITION, OTG, inst), \
+ SRI_ARR(OTG_VERTICAL_INTERRUPT1_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_VERTICAL_INTERRUPT1_POSITION, OTG, inst), \
+ SRI_ARR(OTG_VERTICAL_INTERRUPT2_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_VERTICAL_INTERRUPT2_POSITION, OTG, inst), \
+ SRI_ARR(OPTC_INPUT_CLOCK_CONTROL, ODM, inst), \
+ SRI_ARR(OPTC_DATA_SOURCE_SELECT, ODM, inst), \
+ SRI_ARR(OPTC_INPUT_GLOBAL_CONTROL, ODM, inst), \
+ SRI_ARR(OPTC_RSMU_UNDERFLOW, ODM, inst), \
+ SRI_ARR(OPTC_UNDERFLOW_THRESHOLD, ODM, inst), \
+ SRI_ARR(CONTROL, VTG, inst), \
+ SRI_ARR(OTG_VERT_SYNC_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_GSL_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_CRC_CNTL, OTG, inst), \
+ SRI_ARR(OTG_CRC0_DATA_R, OTG, inst), \
+ SRI_ARR(OTG_CRC0_DATA_G, OTG, inst), \
+ SRI_ARR(OTG_CRC0_DATA_B, OTG, inst), \
+ SRI_ARR(OTG_CRC1_DATA_R, OTG, inst), \
+ SRI_ARR(OTG_CRC1_DATA_G, OTG, inst), \
+ SRI_ARR(OTG_CRC1_DATA_B, OTG, inst), \
+ SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_CRC1_WINDOWA_X_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_CRC1_WINDOWA_Y_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_CRC1_WINDOWB_X_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_CRC1_WINDOWB_Y_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_CRC0_WINDOWA_X_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC0_WINDOWA_Y_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC0_WINDOWB_X_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC0_WINDOWB_Y_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC1_WINDOWA_X_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC1_WINDOWA_Y_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC1_WINDOWB_X_CONTROL_READBACK, OTG, inst),\
+ SRI_ARR(OTG_CRC1_WINDOWB_Y_CONTROL_READBACK, OTG, inst),\
+ SR_ARR(GSL_SOURCE_SELECT, inst), \
+ SRI_ARR(OTG_TRIGA_MANUAL_TRIG, OTG, inst), \
+ SRI_ARR(OTG_GLOBAL_CONTROL1, OTG, inst), \
+ SRI_ARR(OTG_GLOBAL_CONTROL2, OTG, inst), \
+ SRI_ARR(OTG_GSL_WINDOW_X, OTG, inst), \
+ SRI_ARR(OTG_GSL_WINDOW_Y, OTG, inst), \
+ SRI_ARR(OTG_VUPDATE_KEEPOUT, OTG, inst), \
+ SRI_ARR(OTG_DRR_TRIGGER_WINDOW, OTG, inst), \
+ SRI_ARR(OTG_DRR_V_TOTAL_CHANGE, OTG, inst), \
+ SRI_ARR(OPTC_DATA_FORMAT_CONTROL, ODM, inst), \
+ SRI_ARR(OPTC_BYTES_PER_PIXEL, ODM, inst), \
+ SRI_ARR(OPTC_WIDTH_CONTROL, ODM, inst), \
+ SRI_ARR(OPTC_WIDTH_CONTROL2, ODM, inst), \
+ SRI_ARR(OPTC_MEMORY_CONFIG, ODM, inst), \
+ SRI_ARR(OTG_DRR_CONTROL, OTG, inst), \
+ SRI_ARR(OTG_PSTATE_REGISTER, OTG, inst), \
+ SRI_ARR(OTG_PWA_FRAME_SYNC_CONTROL, OTG, inst),\
+ SRI_ARR(OTG_PIPE_UPDATE_STATUS, OTG, inst),\
+ SRI_ARR(INTERRUPT_DEST, OTG, inst)
+
+/* CLK SRC */
+#define CS_COMMON_REG_LIST_DCN42_RI(index, pllid) \
+ SRI_ARR_ALPHABET(PIXCLK_RESYNC_CNTL, PHYPLL, index, pllid), \
+ SRII_ARR_2(PHASE, DP_DTO, 0, index), \
+ SRII_ARR_2(PHASE, DP_DTO, 1, index), \
+ SRII_ARR_2(PHASE, DP_DTO, 2, index), \
+ SRII_ARR_2(PHASE, DP_DTO, 3, index), \
+ SRII_ARR_2(MODULO, DP_DTO, 0, index), \
+ SRII_ARR_2(MODULO, DP_DTO, 1, index), \
+ SRII_ARR_2(MODULO, DP_DTO, 2, index), \
+ SRII_ARR_2(MODULO, DP_DTO, 3, index), \
+ SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 0, index), \
+ SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 1, index), \
+ SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 2, index), \
+ SRII_ARR_2(PIXEL_RATE_CNTL, OTG, 3, index)
+
+/* ABM */
+#define ABM_DCN42_REG_LIST_RI(id) \
+ SRI_ARR(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \
+ SRI_ARR(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \
+ SRI_ARR(DC_ABM1_HG_MISC_CTRL, ABM, id), \
+ SRI_ARR(DC_ABM1_IPCSC_COEFF_SEL, ABM, id), \
+ SRI_ARR(BL1_PWM_BL_UPDATE_SAMPLE_RATE, ABM, id), \
+ SRI_ARR(BL1_PWM_CURRENT_ABM_LEVEL, ABM, id), \
+ SRI_ARR(BL1_PWM_TARGET_ABM_LEVEL, ABM, id), \
+ SRI_ARR(BL1_PWM_USER_LEVEL, ABM, id), \
+ SRI_ARR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \
+ SRI_ARR(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \
+ SRI_ARR(DC_ABM1_HG_BIN_33_40_SHIFT_INDEX, ABM, id), \
+ SRI_ARR(DC_ABM1_HG_BIN_33_64_SHIFT_FLAG, ABM, id), \
+ SRI_ARR(DC_ABM1_HG_BIN_41_48_SHIFT_INDEX, ABM, id), \
+ SRI_ARR(DC_ABM1_HG_BIN_49_56_SHIFT_INDEX, ABM, id), \
+ SRI_ARR(DC_ABM1_HG_BIN_57_64_SHIFT_INDEX, ABM, id), \
+ SRI_ARR(DC_ABM1_HG_RESULT_DATA, ABM, id), \
+ SRI_ARR(DC_ABM1_HG_RESULT_INDEX, ABM, id), \
+ SRI_ARR(DC_ABM1_ACE_OFFSET_SLOPE_DATA, ABM, id), \
+ SRI_ARR(DC_ABM1_ACE_PWL_CNTL, ABM, id)
+
+/* HUBP */
+#define HUBP_REG_LIST_DCN42_RI(id) \
+ HUBP_REG_LIST_DCN30_RI(id), SRI_ARR(DCHUBP_MALL_CONFIG, HUBP, id), \
+ SRI_ARR(DCHUBP_VMPG_CONFIG, HUBP, id), \
+ SRI_ARR(UCLK_PSTATE_FORCE, HUBPREQ, id), \
+ SRI_ARR(HUBP_3DLUT_DLG_PARAM, CURSOR0_, id), \
+ HUBP_3DLUT_FL_REG_LIST_DCN401(id)
+struct dcn42_resource_pool {
+ struct resource_pool base;
+};
+struct resource_pool *dcn42_create_resource_pool(
+ const struct dc_init_data *init_data,
+ struct dc *dc);
+
+enum dc_status dcn42_validate_bandwidth(struct dc *dc,
+ struct dc_state *context,
+ enum dc_validate_mode validate_mode);
+
+void dcn42_prepare_mcache_programming(struct dc *dc, struct dc_state *context);
+int dcn42_get_power_profile(const struct dc_state *context);
+
+#endif /* _DCN42_RESOURCE_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.c b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.c
new file mode 100644
index 000000000000..33b9775420d3
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+
+
+#include "dc.h"
+#include "dcn42_resource_fpu.h"
+
+#define DC_LOGGER_INIT(logger)
+
+
+void dcn42_decide_zstate_support(struct dc *dc, struct dc_state *context)
+{
+ enum dcn_zstate_support_state support = DCN_ZSTATE_SUPPORT_DISALLOW;
+ unsigned int i, plane_count = 0;
+
+ DC_LOGGER_INIT(dc->ctx->logger);
+
+ dc_assert_fp_enabled();
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ if (context->res_ctx.pipe_ctx[i].plane_state)
+ plane_count++;
+ }
+ /*dcn42 has no z10*/
+ if (context->stream_count == 0 || plane_count == 0) {
+ support = DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY;
+ } else if (context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) {
+ struct dc_link *link = context->streams[0]->sink->link;
+ bool is_psr = (link && (link->psr_settings.psr_version == DC_PSR_VERSION_1 ||
+ link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) && !link->panel_config.psr.disable_psr);
+ bool is_replay = link && link->replay_settings.replay_feature_enabled;
+
+ if (is_psr || is_replay)
+ support = DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY;
+ else {
+ /*here we allow z8 for eDP based on dml21 output*/
+ support = context->bw_ctx.bw.dcn.clk.zstate_support ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY : DCN_ZSTATE_SUPPORT_DISALLOW;
+ }
+
+ DC_LOG_SMU("zstate_support: %d, StutterPeriod: %d\n, z8_stutter_efficiency: %d\n",
+ support, (int)context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_period,
+ (int)context->bw_ctx.bw.dcn.clk.stutter_efficiency.z8_stutter_efficiency);
+ }
+ context->bw_ctx.bw.dcn.clk.zstate_support = support;
+
+}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.h
index eca3e5168089..e32103220507 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dce60/dce60_clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn42/dcn42_resource_fpu.h
@@ -1,5 +1,6 @@
+/* SPDX-License-Identifier: MIT */
/*
- * Copyright 2020 Mauro Rossi <issor.oruam@gmail.com>
+ * Copyright 2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -19,18 +20,14 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
- * Authors: AMD
- *
*/
-#ifndef DAL_DC_DCE_DCE60_CLK_MGR_H_
-#define DAL_DC_DCE_DCE60_CLK_MGR_H_
+#ifndef _DCN42_RESOURCE_FPU_H_
+#define _DCN42_RESOURCE_FPU_H_
-#include "dc.h"
+#include "core_types.h"
-void dce60_clk_mgr_construct(
- struct dc_context *ctx,
- struct clk_mgr_internal *clk_mgr_dce);
+void dcn42_decide_zstate_support(struct dc *dc, struct dc_state *context);
-#endif /* DAL_DC_DCE_DCE60_CLK_MGR_H_ */
+#endif /* _DCN42_RESOURCE_FPU_H_ */
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 bc93356a0b5b..d168fb1eacf7 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
@@ -8,11 +8,14 @@ soc_and_ip_translator_ccflags := $(CC_FLAGS_FPU)
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_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)
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
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/dc/soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.c b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.c
index 3190c76eb482..1b397fa7e05c 100644
--- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.c
+++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.c
@@ -102,6 +102,9 @@ static void dcn401_convert_dc_clock_table_to_soc_bb_clock_table(
}
} else {
dml_clk_table->uclk.clk_values_khz[i] = dc_clk_table->entries[i].memclk_mhz * 1000;
+ #ifdef ENABLE_WCK
+ dml_clk_table->wck_ratio.clk_values_khz[i] = dc_clk_table->entries[i].wck_ratio;
+ #endif
}
} else {
dml_clk_table->uclk.clk_values_khz[i] = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c
index c9e224d262c9..146a6e47934b 100644
--- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c
+++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.c
@@ -3,7 +3,7 @@
// Copyright 2025 Advanced Micro Devices, Inc.
#include "dcn42_soc_and_ip_translator.h"
-#include "soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.h"
+#include "../dcn401/dcn401_soc_and_ip_translator.h"
#include "bounding_boxes/dcn42_soc_bb.h"
/* soc_and_ip_translator component used to get up-to-date values for bounding box.
@@ -11,13 +11,180 @@
* This component provides an interface to get DCN-specific bounding box values.
*/
+static void get_default_soc_bb(struct dml2_soc_bb *soc_bb, const struct dc *dc)
+{
+ {
+ memcpy(soc_bb, &dml2_socbb_dcn42, sizeof(struct dml2_soc_bb));
+ memcpy(&soc_bb->qos_parameters, &dml_dcn42_variant_a_soc_qos_params, sizeof(struct dml2_soc_qos_parameters));
+ }
+}
+
+/*
+ * DC clock table is obtained from SMU during runtime.
+ * SMU stands for System Management Unit. It is a power management processor.
+ * It owns the initialization of dc's clock table and programming of clock values
+ * based on dc's requests.
+ * Our clock values in base soc bb is a dummy placeholder. The real clock values
+ * are retrieved from SMU firmware to dc clock table at runtime.
+ * This function overrides our dummy placeholder values with real values in dc
+ * clock table.
+ */
+static void dcn42_convert_dc_clock_table_to_soc_bb_clock_table(
+ struct dml2_soc_state_table *dml_clk_table,
+ struct dml2_soc_vmin_clock_limits *vmin_limit,
+ const struct clk_bw_params *dc_bw_params)
+{
+ int i;
+ const struct clk_limit_table *dc_clk_table;
+
+ if (dc_bw_params == NULL)
+ /* skip if bw params could not be obtained from smu */
+ return;
+
+ dc_clk_table = &dc_bw_params->clk_table;
+
+ /* fclk/dcfclk - dcn42 pmfw table can have 0 entries for inactive dpm levels
+ * for use with dml we need to fill in using an active value aiming for >= 2x DCFCLK
+ */
+ if (dc_clk_table->num_entries_per_clk.num_fclk_levels && dc_clk_table->num_entries_per_clk.num_dcfclk_levels) {
+ dml_clk_table->fclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dcfclk_levels;
+ dml_clk_table->dcfclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dcfclk_levels;
+ for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
+ if (i < dc_clk_table->num_entries_per_clk.num_dcfclk_levels) {
+ int j, max_fclk = 0;
+
+ dml_clk_table->dcfclk.clk_values_khz[i] = dc_clk_table->entries[i].dcfclk_mhz * 1000;
+ for (j = 0; j < MAX_NUM_DPM_LVL; j++) {
+ if (dc_clk_table->entries[j].fclk_mhz * 1000 > max_fclk)
+ max_fclk = dc_clk_table->entries[j].fclk_mhz * 1000;
+ dml_clk_table->fclk.clk_values_khz[i] = max_fclk;
+ if (max_fclk >= 2 * dml_clk_table->dcfclk.clk_values_khz[i])
+ break;
+ }
+ } else {
+ dml_clk_table->dcfclk.clk_values_khz[i] = 0;
+ dml_clk_table->fclk.clk_values_khz[i] = 0;
+ }
+ }
+ }
+
+ /* uclk */
+ if (dc_clk_table->num_entries_per_clk.num_memclk_levels) {
+ dml_clk_table->uclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_memclk_levels;
+ for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
+ if (i < dml_clk_table->uclk.num_clk_values) {
+ dml_clk_table->uclk.clk_values_khz[i] = dc_clk_table->entries[i].memclk_mhz * 1000;
+ dml_clk_table->wck_ratio.clk_values_khz[i] = dc_clk_table->entries[i].wck_ratio;
+ } else {
+ dml_clk_table->uclk.clk_values_khz[i] = 0;
+ dml_clk_table->wck_ratio.clk_values_khz[i] = 0;
+ }
+ }
+ }
+
+ /* dispclk */
+ if (dc_clk_table->num_entries_per_clk.num_dispclk_levels) {
+ dml_clk_table->dispclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dispclk_levels;
+ for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
+ if (i < dml_clk_table->dispclk.num_clk_values) {
+ dml_clk_table->dispclk.clk_values_khz[i] = dc_clk_table->entries[i].dispclk_mhz * 1000;
+ } else {
+ dml_clk_table->dispclk.clk_values_khz[i] = 0;
+ }
+ }
+ vmin_limit->dispclk_khz = min(dc_clk_table->entries[0].dispclk_mhz * 1000, vmin_limit->dispclk_khz);
+ /* dispclk is always fine-grain */
+ dml_clk_table->dispclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dispclk_levels >= 2 ? 2 : 1;
+ dml_clk_table->dispclk.clk_values_khz[0] = 0;
+ dml_clk_table->dispclk.clk_values_khz[1] = dc_clk_table->entries[dc_clk_table->num_entries_per_clk.num_dispclk_levels - 1].dispclk_mhz * 1000;
+ }
+
+ /* dppclk */
+ if (dc_clk_table->num_entries_per_clk.num_dppclk_levels) {
+ dml_clk_table->dppclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dppclk_levels;
+ for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
+ if (i < dml_clk_table->dppclk.num_clk_values) {
+ dml_clk_table->dppclk.clk_values_khz[i] = dc_clk_table->entries[i].dppclk_mhz * 1000;
+ } else {
+ dml_clk_table->dppclk.clk_values_khz[i] = 0;
+ }
+ }
+ /* dppclk is always fine-grain */
+ dml_clk_table->dppclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dppclk_levels >= 2 ? 2 : 1;
+ dml_clk_table->dppclk.clk_values_khz[0] = 0;
+ dml_clk_table->dppclk.clk_values_khz[1] = dc_clk_table->entries[dc_clk_table->num_entries_per_clk.num_dppclk_levels - 1].dppclk_mhz * 1000;
+ }
+
+ /* dtbclk */
+ if (dc_clk_table->num_entries_per_clk.num_dtbclk_levels) {
+ dml_clk_table->dtbclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_dtbclk_levels;
+ for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
+ if (i < dml_clk_table->dtbclk.num_clk_values) {
+ dml_clk_table->dtbclk.clk_values_khz[i] = dc_clk_table->entries[i].dtbclk_mhz * 1000;
+ } else {
+ dml_clk_table->dtbclk.clk_values_khz[i] = 0;
+ }
+ }
+ }
+
+ /* socclk */
+ if (dc_clk_table->num_entries_per_clk.num_socclk_levels) {
+ dml_clk_table->socclk.num_clk_values = dc_clk_table->num_entries_per_clk.num_socclk_levels;
+ for (i = 0; i < min(DML_MAX_CLK_TABLE_SIZE, MAX_NUM_DPM_LVL); i++) {
+ if (i < dml_clk_table->socclk.num_clk_values) {
+ dml_clk_table->socclk.clk_values_khz[i] = dc_clk_table->entries[i].socclk_mhz * 1000;
+ } else {
+ dml_clk_table->socclk.clk_values_khz[i] = 0;
+ }
+ }
+ }
+
+ /* dram config */
+ dml_clk_table->dram_config.channel_count = dc_bw_params->num_channels;
+ dml_clk_table->dram_config.channel_width_bytes = dc_bw_params->dram_channel_width_bytes;
+}
+
+static void dcn42_update_soc_bb_with_values_from_clk_mgr(struct dml2_soc_bb *soc_bb, const struct dc *dc)
+{
+ soc_bb->dprefclk_mhz = dc->clk_mgr->dprefclk_khz / 1000;
+ soc_bb->dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0;
+ soc_bb->mall_allocated_for_dcn_mbytes = dc->caps.mall_size_total / (1024 * 1024);
+
+ if (dc->clk_mgr->funcs->is_smu_present &&
+ dc->clk_mgr->funcs->is_smu_present(dc->clk_mgr)) {
+ dcn42_convert_dc_clock_table_to_soc_bb_clock_table(&soc_bb->clk_table, &soc_bb->vmin_limit,
+ dc->clk_mgr->bw_params);
+ }
+}
+
+static void apply_soc_bb_updates(struct dml2_soc_bb *soc_bb, const struct dc *dc, const struct dml2_configuration_options *config)
+{
+ (void)config;
+ /* Individual modification can be overwritten even if it was obtained by a previous function.
+ * Modifications are acquired in order of priority (lowest to highest).
+ */
+ dc_assert_fp_enabled();
+
+ dcn42_update_soc_bb_with_values_from_clk_mgr(soc_bb, dc);
+ dcn401_update_soc_bb_with_values_from_vbios(soc_bb, dc);
+ dcn401_update_soc_bb_with_values_from_software_policy(soc_bb, dc);
+}
+
+void dcn42_get_soc_bb(struct dml2_soc_bb *soc_bb, const struct dc *dc, const struct dml2_configuration_options *config)
+{
+ //get default soc_bb with static values
+ get_default_soc_bb(soc_bb, dc);
+ //update soc_bb values with more accurate values
+ apply_soc_bb_updates(soc_bb, dc, config);
+}
+
static void dcn42_get_ip_caps(struct dml2_ip_capabilities *ip_caps)
{
*ip_caps = dml2_dcn42_max_ip_caps;
}
static struct soc_and_ip_translator_funcs dcn42_translator_funcs = {
- .get_soc_bb = dcn401_get_soc_bb,
+ .get_soc_bb = dcn42_get_soc_bb,
.get_ip_caps = dcn42_get_ip_caps,
};
@@ -25,3 +192,4 @@ void dcn42_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc_and
{
soc_and_ip_translator->translator_funcs = &dcn42_translator_funcs;
}
+
diff --git a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.h b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.h
index 914dcbb369a7..1dded5426152 100644
--- a/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.h
+++ b/drivers/gpu/drm/amd/display/dc/soc_and_ip_translator/dcn42/dcn42_soc_and_ip_translator.h
@@ -12,5 +12,6 @@
#include "soc_and_ip_translator.h"
void dcn42_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc_and_ip_translator);
+void dcn42_get_soc_bb(struct dml2_soc_bb *soc_bb, const struct dc *dc, const struct dml2_configuration_options *config);
#endif /* _DCN42_SOC_AND_IP_TRANSLATOR_H_ */
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 6617c9d2d5f8..bad0bd79fa94 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
@@ -4,6 +4,7 @@
#include "soc_and_ip_translator.h"
#include "soc_and_ip_translator/dcn401/dcn401_soc_and_ip_translator.h"
+#include "soc_and_ip_translator/dcn42/dcn42_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)
@@ -12,6 +13,9 @@ static void dc_construct_soc_and_ip_translator(struct soc_and_ip_translator *soc
case DCN_VERSION_4_01:
dcn401_construct_soc_and_ip_translator(soc_and_ip_translator);
break;
+ case DCN_VERSION_4_2:
+ dcn42_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 3b6bba017040..c18ff8f00bb8 100644
--- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h
@@ -1,5 +1,6 @@
+/* SPDX-License-Identifier: MIT */
/*
- * Copyright 2019 Advanced Micro Devices, Inc.
+ * Copyright 2019-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -119,6 +120,7 @@ enum dmub_asic {
DMUB_ASIC_DCN351,
DMUB_ASIC_DCN36,
DMUB_ASIC_DCN401,
+ DMUB_ASIC_DCN42,
DMUB_ASIC_MAX,
};
@@ -602,6 +604,7 @@ struct dmub_srv {
struct dmub_srv_dcn32_regs *regs_dcn32;
struct dmub_srv_dcn35_regs *regs_dcn35;
const struct dmub_srv_dcn401_regs *regs_dcn401;
+ struct dmub_srv_dcn42_regs *regs_dcn42;
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 6f388c910e18..fe9431cea3e5 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -909,7 +909,8 @@ union dmub_fw_meta_feature_bits {
struct {
uint32_t shared_state_link_detection : 1; /**< 1 supports link detection via shared state */
uint32_t cursor_offload_v1_support: 1; /**< 1 supports cursor offload */
- uint32_t reserved : 30;
+ uint32_t inbox0_lock_support: 1; /**< 1 supports inbox0 lock mechanism */
+ uint32_t reserved : 29;
} bits; /**< status bits */
uint32_t all; /**< 32-bit access to status bits */
};
@@ -1535,14 +1536,12 @@ enum dmub_gpint_command {
* 1 - Enable ips measurement
*/
DMUB_GPINT__IPS_RESIDENCY = 121,
-
/**
* DESC: Enable measurements for various task duration
* ARGS: 0 - Disable measurement
* 1 - Enable measurement
*/
DMUB_GPINT__TRACE_DMUB_WAKE_ACTIVITY = 123,
-
/**
* DESC: Gets IPS residency in microseconds
* ARGS: 0 - Return IPS1 residency
@@ -1552,21 +1551,18 @@ enum dmub_gpint_command {
* RETURN: Total residency in microseconds - lower 32 bits
*/
DMUB_GPINT__GET_IPS_RESIDENCY_DURATION_US_LO = 124,
-
/**
* DESC: Gets IPS1 histogram counts
* ARGS: Bucket index
* RETURN: Total count for the bucket
*/
DMUB_GPINT__GET_IPS1_HISTOGRAM_COUNTER = 125,
-
/**
* DESC: Gets IPS2 histogram counts
* ARGS: Bucket index
* RETURN: Total count for the bucket
*/
DMUB_GPINT__GET_IPS2_HISTOGRAM_COUNTER = 126,
-
/**
* DESC: Gets IPS residency
* ARGS: 0 - Return IPS1 residency
@@ -1576,21 +1572,18 @@ enum dmub_gpint_command {
* RETURN: Total residency in milli-percent.
*/
DMUB_GPINT__GET_IPS_RESIDENCY_PERCENT = 127,
-
/**
* DESC: Gets IPS1_RCG histogram counts
* ARGS: Bucket index
* RETURN: Total count for the bucket
*/
DMUB_GPINT__GET_IPS1_RCG_HISTOGRAM_COUNTER = 128,
-
/**
* DESC: Gets IPS1_ONO2_ON histogram counts
* ARGS: Bucket index
* RETURN: Total count for the bucket
*/
DMUB_GPINT__GET_IPS1_ONO2_ON_HISTOGRAM_COUNTER = 129,
-
/**
* DESC: Gets IPS entry counter during residency measurement
* ARGS: 0 - Return IPS1 entry counts
@@ -1600,7 +1593,6 @@ enum dmub_gpint_command {
* RETURN: Entry counter for selected IPS mode
*/
DMUB_GPINT__GET_IPS_RESIDENCY_ENTRY_COUNTER = 130,
-
/**
* DESC: Gets IPS inactive residency in microseconds
* ARGS: 0 - Return IPS1_MAX residency
@@ -1610,7 +1602,6 @@ enum dmub_gpint_command {
* RETURN: Total inactive residency in microseconds - lower 32 bits
*/
DMUB_GPINT__GET_IPS_INACTIVE_RESIDENCY_DURATION_US_LO = 131,
-
/**
* DESC: Gets IPS inactive residency in microseconds
* ARGS: 0 - Return IPS1_MAX residency
@@ -1620,7 +1611,6 @@ enum dmub_gpint_command {
* RETURN: Total inactive residency in microseconds - upper 32 bits
*/
DMUB_GPINT__GET_IPS_INACTIVE_RESIDENCY_DURATION_US_HI = 132,
-
/**
* DESC: Gets IPS residency in microseconds
* ARGS: 0 - Return IPS1 residency
@@ -1679,7 +1669,7 @@ union dmub_inbox0_cmd_lock_hw {
uint32_t lock: 1; /**< Lock */
uint32_t should_release: 1; /**< Release */
- uint32_t reserved: 7; /**< Reserved for extending more clients, HW, etc. */
+ uint32_t reserved: 7; /**< Reserved for extending more clients, HW, etc. */
} bits;
uint32_t all;
};
@@ -1897,6 +1887,15 @@ enum dmub_cmd_type {
*/
DMUB_CMD__PR = 94,
+ /**
+ * Command type used for all IHC commands.
+ */
+ DMUB_CMD__IHC = 95,
+
+ /**
+ * Command type use for boot time crc commands.
+ */
+ DMUB_CMD__BOOT_TIME_CRC = 96,
/**
* Command type use for VBIOS shared commands.
@@ -2610,9 +2609,9 @@ struct dmub_fams2_stream_static_state {
uint8_t allow_to_target_delay_otg_vlines; // time from allow vline to target vline
union {
struct {
- uint8_t is_drr: 1; // stream is DRR enabled
- uint8_t clamp_vtotal_min: 1; // clamp vtotal to min instead of nominal
- uint8_t min_ttu_vblank_usable: 1; // if min ttu vblank is above wm, no force pstate is needed in blank
+ uint8_t is_drr : 1; // stream is DRR enabled
+ uint8_t clamp_vtotal_min : 1; // clamp vtotal to min instead of nominal
+ uint8_t min_ttu_vblank_usable : 1; // if min ttu vblank is above wm, no force pstate is needed in blank
} bits;
uint8_t all;
} config;
@@ -4437,6 +4436,8 @@ enum dmub_cmd_replay_general_subtype {
REPLAY_GENERAL_CMD_SET_LOW_RR_ACTIVATE,
REPLAY_GENERAL_CMD_VIDEO_CONFERENCING,
REPLAY_GENERAL_CMD_SET_CONTINUOUSLY_RESYNC,
+ REPLAY_GENERAL_CMD_SET_COASTING_VTOTAL_WITHOUT_FRAME_UPDATE,
+ REPLAY_GENERAL_CMD_LIVE_CAPTURE_WITH_CVT,
};
struct dmub_alpm_auxless_data {
@@ -4655,6 +4656,18 @@ struct dmub_rb_cmd_replay_enable_data {
* This does not support HDMI/DP2 for now.
*/
uint8_t phy_rate;
+ /**
+ * @hpo_stream_enc_inst: HPO stream encoder instance
+ */
+ uint8_t hpo_stream_enc_inst;
+ /**
+ * @hpo_link_enc_inst: HPO link encoder instance
+ */
+ uint8_t hpo_link_enc_inst;
+ /**
+ * @pad: Align structure to 4 byte boundary.
+ */
+ uint8_t pad[2];
};
/**
@@ -4960,6 +4973,52 @@ union dmub_replay_cmd_set {
};
/**
+ * IHC command sub-types.
+ */
+enum dmub_cmd_ihc_type {
+ /**
+ * Set DIG HDCP interrupt destination.
+ */
+ DMUB_CMD__IHC_SET_DIG_HDCP_INTERRUPT_DEST = 0,
+};
+
+/**
+ * Data passed from driver to FW in a DMUB_CMD__IHC command.
+ */
+struct dmub_cmd_ihc_data {
+ /**
+ * DIG engine ID (0-3).
+ */
+ uint8_t dig_id;
+ /**
+ * 1 = route to DMU, 0 = route to CPU.
+ */
+ uint8_t to_dmu : 1;
+ /**
+ * Reserved bits.
+ */
+ uint8_t reserved : 7;
+ /**
+ * Padding.
+ */
+ uint8_t pad[2];
+};
+
+/**
+ * Definition of a DMUB_CMD__IHC command.
+ */
+struct dmub_rb_cmd_ihc {
+ /**
+ * Command header.
+ */
+ struct dmub_cmd_header header;
+ /**
+ * IHC command data.
+ */
+ struct dmub_cmd_ihc_data data;
+};
+
+/**
* SMART POWER OLED command sub-types.
*/
enum dmub_cmd_smart_power_oled_type {
@@ -5222,8 +5281,8 @@ enum dmub_cmd_lsdma_type {
*/
DMUB_CMD__LSDMA_LINEAR_COPY = 1,
/**
- * LSDMA copies data from source to destination linearly in sub window
- */
+ * LSDMA copies data from source to destination linearly in sub window
+ */
DMUB_CMD__LSDMA_LINEAR_SUB_WINDOW_COPY = 2,
/**
* Send the tiled-to-tiled copy command
@@ -6213,6 +6272,7 @@ struct dmub_cmd_edid_cea_amd_vsdb {
uint16_t amd_vsdb_version; /**< AMD VSDB version */
uint16_t min_frame_rate; /**< Maximum frame rate */
uint16_t max_frame_rate; /**< Minimum frame rate */
+ uint8_t freesync_mccs_vcp_code; /**< Freesync MCCS VCP code */
};
/**
@@ -6786,6 +6846,29 @@ struct dmub_rb_cmd_pr_general_cmd {
};
/**
+ * Command type of a DMUB_CMD__BOOT_TIME_CRC command
+ */
+enum dmub_cmd_boot_time_crc_type {
+ DMUB_CMD__BOOT_TIME_CRC_INIT_MEM = 0
+};
+
+/**
+ * Data passed from driver to FW in a DMUB_CMD__BOOT_TIME_CRC_INIT command.
+ */
+struct dmub_cmd_boot_time_crc_init_data {
+ union dmub_addr buffer_addr;
+ uint32_t buffer_size;
+};
+
+/**
+ * Definition of a DMUB_CMD__BOOT_TIME_CRC_INIT command.
+ */
+struct dmub_rb_cmd_boot_time_crc_init {
+ struct dmub_cmd_header header;
+ struct dmub_cmd_boot_time_crc_init_data data;
+};
+
+/**
* union dmub_rb_cmd - DMUB inbox command.
*/
union dmub_rb_cmd {
@@ -7142,6 +7225,14 @@ union dmub_rb_cmd {
struct dmub_rb_cmd_pr_update_state pr_update_state;
struct dmub_rb_cmd_pr_general_cmd pr_general_cmd;
+ /**
+ * Definition of a DMUB_CMD__IHC command.
+ */
+ struct dmub_rb_cmd_ihc ihc;
+ /**
+ * Definition of a DMUB_CMD__BOOT_TIME_CRC_INIT command.
+ */
+ struct dmub_rb_cmd_boot_time_crc_init boot_time_crc_init;
};
/**
diff --git a/drivers/gpu/drm/amd/display/dmub/src/Makefile b/drivers/gpu/drm/amd/display/dmub/src/Makefile
index 468b768c11ae..ac7b17d8fb0f 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/Makefile
+++ b/drivers/gpu/drm/amd/display/dmub/src/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright 2019 Advanced Micro Devices, Inc.
+# Copyright 2019-2026 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
@@ -28,6 +28,7 @@ DMUB += dmub_dcn35.o
DMUB += dmub_dcn351.o
DMUB += dmub_dcn36.o
DMUB += dmub_dcn401.o
+DMUB += dmub_dcn42.o
AMD_DAL_DMUB = $(addprefix $(AMDDALPATH)/dmub/src/,$(DMUB))
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
index 54df2147e4dc..0b152926f75b 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn20.c
@@ -194,6 +194,7 @@ void dmub_dcn20_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw6,
const struct dmub_window *region6)
{
+ (void)region6;
union dmub_addr offset;
uint64_t fb_base, fb_offset;
@@ -396,6 +397,7 @@ union dmub_fw_boot_status dmub_dcn20_get_fw_boot_status(struct dmub_srv *dmub)
void dmub_dcn20_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params)
{
+ (void)params;
union dmub_fw_boot_options boot_options = {0};
REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
@@ -460,20 +462,26 @@ void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub)
dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE);
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
- dmub->debug.is_dmcub_enabled = is_dmub_enabled;
+ ASSERT(is_dmub_enabled <= 0xFF);
+ dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled;
REG_GET(DMCUB_CNTL, DMCUB_SOFT_RESET, &is_soft_reset);
- dmub->debug.is_dmcub_soft_reset = is_soft_reset;
+ ASSERT(is_soft_reset <= 0xFF);
+ dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset;
REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
- dmub->debug.is_dmcub_secure_reset = is_sec_reset;
+ ASSERT(is_sec_reset <= 0xFF);
+ dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset;
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
- dmub->debug.is_traceport_en = is_traceport_enabled;
+ ASSERT(is_traceport_enabled <= 0xFF);
+ dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled;
REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
- dmub->debug.is_cw0_enabled = is_cw0_enabled;
+ ASSERT(is_cw0_enabled <= 0xFF);
+ dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled;
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
- dmub->debug.is_cw6_enabled = is_cw6_enabled;
+ ASSERT(is_cw6_enabled <= 0xFF);
+ dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled;
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
index 84a6eb3f677d..23a33db07edc 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn30.c
@@ -127,6 +127,7 @@ void dmub_dcn30_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw6,
const struct dmub_window *region6)
{
+ (void)region6;
union dmub_addr offset;
/* sienna_cichlid has hardwired virtual addressing for CW2-CW7 */
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
index a0cefc03b21d..478d79a6e246 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
@@ -195,6 +195,8 @@ void dmub_dcn31_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw6,
const struct dmub_window *region6)
{
+ (void)cw2;
+ (void)region6;
union dmub_addr offset;
offset = cw3->offset;
@@ -466,25 +468,32 @@ void dmub_dcn31_get_diagnostic_data(struct dmub_srv *dmub)
dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE);
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
- dmub->debug.is_dmcub_enabled = is_dmub_enabled;
+ ASSERT(is_dmub_enabled <= 0xFF);
+ dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled;
REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait);
- dmub->debug.is_pwait = is_pwait;
+ ASSERT(is_pwait <= 0xFF);
+ dmub->debug.is_pwait = (uint8_t)is_pwait;
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
- dmub->debug.is_dmcub_soft_reset = is_soft_reset;
+ ASSERT(is_soft_reset <= 0xFF);
+ dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset;
REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
- dmub->debug.is_dmcub_secure_reset = is_sec_reset;
+ ASSERT(is_sec_reset <= 0xFF);
+ dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset;
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
- dmub->debug.is_traceport_en = is_traceport_enabled;
+ ASSERT(is_traceport_enabled <= 0xFF);
+ dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled;
REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
- dmub->debug.is_cw0_enabled = is_cw0_enabled;
+ ASSERT(is_cw0_enabled <= 0xFF);
+ dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled;
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
- dmub->debug.is_cw6_enabled = is_cw6_enabled;
+ ASSERT(is_cw6_enabled <= 0xFF);
+ dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled;
}
bool dmub_dcn31_should_detect(struct dmub_srv *dmub)
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
index 2f99a2772599..3f9fb9e05b79 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn32.c
@@ -237,6 +237,8 @@ void dmub_dcn32_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw6,
const struct dmub_window *region6)
{
+ (void)cw2;
+ (void)region6;
union dmub_addr offset;
offset = cw3->offset;
@@ -486,19 +488,24 @@ void dmub_dcn32_get_diagnostic_data(struct dmub_srv *dmub)
dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE);
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
- dmub->debug.is_dmcub_enabled = is_dmub_enabled;
+ ASSERT(is_dmub_enabled <= 0xFF);
+ dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled;
REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait);
- dmub->debug.is_pwait = is_pwait;
+ ASSERT(is_pwait <= 0xFF);
+ dmub->debug.is_pwait = (uint8_t)is_pwait;
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
- dmub->debug.is_dmcub_soft_reset = is_soft_reset;
+ ASSERT(is_soft_reset <= 0xFF);
+ dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset;
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
- dmub->debug.is_traceport_en = is_traceport_enabled;
+ ASSERT(is_traceport_enabled <= 0xFF);
+ dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled;
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
- dmub->debug.is_cw6_enabled = is_cw6_enabled;
+ ASSERT(is_cw6_enabled <= 0xFF);
+ dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled;
dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0);
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
index 639f9835e5e9..69fb6084232e 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c
@@ -222,6 +222,7 @@ void dmub_dcn35_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw6,
const struct dmub_window *region6)
{
+ (void)cw2;
union dmub_addr offset;
offset = cw3->offset;
@@ -402,7 +403,7 @@ void dmub_dcn35_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmu
union dmub_fw_boot_options boot_options = {0};
if (!dmub->dpia_supported) {
- dmub->dpia_supported = dmub_dcn35_get_fw_boot_option(dmub).bits.enable_dpia;
+ dmub->dpia_supported = dmub_dcn35_get_fw_boot_option(dmub).bits.enable_dpia != 0;
}
boot_options.bits.z10_disable = params->disable_z10;
@@ -508,19 +509,24 @@ void dmub_dcn35_get_diagnostic_data(struct dmub_srv *dmub)
dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE);
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
- dmub->debug.is_dmcub_enabled = is_dmub_enabled;
+ ASSERT(is_dmub_enabled <= 0xFF);
+ dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled;
REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait);
- dmub->debug.is_pwait = is_pwait;
+ ASSERT(is_pwait <= 0xFF);
+ dmub->debug.is_pwait = (uint8_t)is_pwait;
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
- dmub->debug.is_dmcub_soft_reset = is_soft_reset;
+ ASSERT(is_soft_reset <= 0xFF);
+ dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset;
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
- dmub->debug.is_traceport_en = is_traceport_enabled;
+ ASSERT(is_traceport_enabled <= 0xFF);
+ dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled;
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
- dmub->debug.is_cw6_enabled = is_cw6_enabled;
+ ASSERT(is_cw6_enabled <= 0xFF);
+ dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled;
dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0);
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c
index 16ed07f0e96d..e5a78df80d72 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c
@@ -213,6 +213,7 @@ void dmub_dcn401_setup_windows(struct dmub_srv *dmub,
const struct dmub_window *cw6,
const struct dmub_window *region6)
{
+ (void)cw2;
union dmub_addr offset;
offset = cw3->offset;
@@ -473,25 +474,32 @@ void dmub_dcn401_get_diagnostic_data(struct dmub_srv *dmub)
dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE);
REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
- dmub->debug.is_dmcub_enabled = is_dmub_enabled;
+ ASSERT(is_dmub_enabled <= 0xFF);
+ dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled;
REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait);
- dmub->debug.is_pwait = is_pwait;
+ ASSERT(is_pwait <= 0xFF);
+ dmub->debug.is_pwait = (uint8_t)is_pwait;
REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
- dmub->debug.is_dmcub_soft_reset = is_soft_reset;
+ ASSERT(is_soft_reset <= 0xFF);
+ dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset;
REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
- dmub->debug.is_dmcub_secure_reset = is_sec_reset;
+ ASSERT(is_sec_reset <= 0xFF);
+ dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset;
REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
- dmub->debug.is_traceport_en = is_traceport_enabled;
+ ASSERT(is_traceport_enabled <= 0xFF);
+ dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled;
REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
- dmub->debug.is_cw0_enabled = is_cw0_enabled;
+ ASSERT(is_cw0_enabled <= 0xFF);
+ dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled;
REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
- dmub->debug.is_cw6_enabled = is_cw6_enabled;
+ ASSERT(is_cw6_enabled <= 0xFF);
+ dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled;
dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0);
}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c
new file mode 100644
index 000000000000..a09aa19ad379
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.c
@@ -0,0 +1,759 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright 2026 Advanced Micro Devices, Inc.
+
+#include "../dmub_srv.h"
+#include "dmub_reg.h"
+#include "dmub_dcn35.h"
+#include "dmub_dcn401.h"
+#include "dmub_dcn42.h"
+
+#include "dcn/dcn_4_2_0_offset.h"
+#include "dcn/dcn_4_2_0_sh_mask.h"
+
+#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg]
+#define CTX dmub
+#define REGS dmub->regs_dcn42
+#define REG_OFFSET_EXP(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name)
+
+void dmub_srv_dcn42_regs_init(struct dmub_srv *dmub, struct dc_context *ctx)
+{
+ struct dmub_srv_dcn42_regs *regs = dmub->regs_dcn42;
+#define REG_STRUCT regs
+
+#define DMUB_SR(reg) REG_STRUCT->offset.reg = REG_OFFSET_EXP(reg);
+ DMUB_DCN42_REGS()
+ DMCUB_INTERNAL_REGS()
+#undef DMUB_SR
+
+#define DMUB_SF(reg, field) REG_STRUCT->mask.reg##__##field = FD_MASK(reg, field);
+ DMUB_DCN42_FIELDS()
+#undef DMUB_SF
+
+#define DMUB_SF(reg, field) REG_STRUCT->shift.reg##__##field = FD_SHIFT(reg, field);
+ DMUB_DCN42_FIELDS()
+#undef DMUB_SF
+#undef REG_STRUCT
+}
+
+void dmub_dcn42_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params)
+{
+ union dmub_fw_boot_options boot_options = {0};
+
+ if (!dmub->dpia_supported) {
+ dmub->dpia_supported = dmub_dcn42_get_fw_boot_option(dmub).bits.enable_dpia != 0;
+ }
+
+ boot_options.bits.z10_disable = params->disable_z10;
+ boot_options.bits.dpia_supported = params->dpia_supported;
+ boot_options.bits.enable_dpia = dmub->dpia_supported && !params->disable_dpia;
+ boot_options.bits.usb4_cm_version = params->usb4_cm_version;
+ boot_options.bits.dpia_hpd_int_enable_supported = params->dpia_hpd_int_enable_supported;
+ boot_options.bits.power_optimization = params->power_optimization;
+ boot_options.bits.disable_clk_ds = params->disallow_dispclk_dppclk_ds;
+ boot_options.bits.disable_clk_gate = params->disable_clock_gate;
+ boot_options.bits.ips_disable = params->disable_ips;
+ boot_options.bits.ips_sequential_ono = params->ips_sequential_ono;
+ boot_options.bits.disable_sldo_opt = params->disable_sldo_opt;
+ boot_options.bits.enable_non_transparent_setconfig = params->enable_non_transparent_setconfig;
+ boot_options.bits.lower_hbr3_phy_ssc = params->lower_hbr3_phy_ssc;
+ boot_options.bits.skip_phy_access = params->disallow_phy_access;
+ boot_options.bits.disable_dpia_bw_allocation = params->disable_dpia_bw_allocation;
+
+ REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
+}
+
+static void dmub_dcn42_get_fb_base_offset(struct dmub_srv *dmub,
+ uint64_t *fb_base,
+ uint64_t *fb_offset)
+{
+ uint32_t tmp;
+
+ /*
+ if (dmub->soc_fb_info.fb_base || dmub->soc_fb_info.fb_offset) {
+ *fb_base = dmub->soc_fb_info.fb_base;
+ *fb_offset = dmub->soc_fb_info.fb_offset;
+ return;
+ }
+ */
+
+ REG_GET(DCN_VM_FB_LOCATION_BASE, FB_BASE, &tmp);
+ *fb_base = (uint64_t)tmp << 24;
+
+ REG_GET(DCN_VM_FB_OFFSET, FB_OFFSET, &tmp);
+ *fb_offset = (uint64_t)tmp << 24;
+}
+
+static inline void dmub_dcn42_translate_addr(const union dmub_addr *addr_in,
+ uint64_t fb_base,
+ uint64_t fb_offset,
+ union dmub_addr *addr_out)
+{
+ addr_out->quad_part = addr_in->quad_part - fb_base + fb_offset;
+}
+
+void dmub_dcn42_reset(struct dmub_srv *dmub)
+{
+ union dmub_gpint_data_register cmd;
+ const uint32_t timeout = 100000;
+ uint32_t in_reset, is_enabled, scratch, i, pwait_mode;
+
+ REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &in_reset);
+ REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enabled);
+
+ if (in_reset == 0 && is_enabled != 0) {
+ cmd.bits.status = 1;
+ cmd.bits.command_code = DMUB_GPINT__STOP_FW;
+ cmd.bits.param = 0;
+
+ dmub->hw_funcs.set_gpint(dmub, cmd);
+
+ for (i = 0; i < timeout; ++i) {
+ if (dmub->hw_funcs.is_gpint_acked(dmub, cmd))
+ break;
+
+ udelay(1);
+ }
+
+ for (i = 0; i < timeout; ++i) {
+ scratch = REG_READ(DMCUB_SCRATCH7);
+ if (scratch == DMUB_GPINT__STOP_FW_RESPONSE)
+ break;
+
+ udelay(1);
+ }
+
+ for (i = 0; i < timeout; ++i) {
+ REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &pwait_mode);
+ if (pwait_mode & (1 << 0))
+ break;
+
+ udelay(1);
+ }
+ /* Force reset in case we timed out, DMCUB is likely hung. */
+ }
+
+ if (is_enabled) {
+ REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1);
+ udelay(1);
+ REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0);
+ }
+
+ REG_WRITE(DMCUB_INBOX1_RPTR, 0);
+ REG_WRITE(DMCUB_INBOX1_WPTR, 0);
+ REG_WRITE(DMCUB_OUTBOX1_RPTR, 0);
+ REG_WRITE(DMCUB_OUTBOX1_WPTR, 0);
+ REG_WRITE(DMCUB_OUTBOX0_RPTR, 0);
+ REG_WRITE(DMCUB_OUTBOX0_WPTR, 0);
+ REG_WRITE(DMCUB_SCRATCH0, 0);
+
+ /* Clear the GPINT command manually so we don't send anything during boot. */
+ cmd.all = 0;
+ dmub->hw_funcs.set_gpint(dmub, cmd);
+}
+
+void dmub_dcn42_reset_release(struct dmub_srv *dmub)
+{
+ REG_WRITE(DMCUB_SCRATCH15, dmub->psp_version & 0x001100FF);
+
+ REG_UPDATE_3(DMU_CLK_CNTL,
+ LONO_DISPCLK_GATE_DISABLE, 1,
+ LONO_SOCCLK_GATE_DISABLE, 1,
+ LONO_DMCUBCLK_GATE_DISABLE, 1);
+
+ REG_UPDATE_2(DMCUB_CNTL, DMCUB_ENABLE, 1, DMCUB_TRACEPORT_EN, 1);
+ REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 0);
+ REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 0);
+}
+
+void dmub_dcn42_backdoor_load(struct dmub_srv *dmub,
+ const struct dmub_window *cw0,
+ const struct dmub_window *cw1)
+{
+ union dmub_addr offset;
+ uint64_t fb_base, fb_offset;
+
+ dmub_dcn42_get_fb_base_offset(dmub, &fb_base, &fb_offset);
+
+ dmub_dcn42_translate_addr(&cw0->offset, fb_base, fb_offset, &offset);
+
+ REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part);
+ REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part);
+ REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base);
+ REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0,
+ DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top,
+ DMCUB_REGION3_CW0_ENABLE, 1);
+
+ dmub_dcn42_translate_addr(&cw1->offset, fb_base, fb_offset, &offset);
+
+ REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part);
+ REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part);
+ REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base);
+ REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0,
+ DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top,
+ DMCUB_REGION3_CW1_ENABLE, 1);
+
+ /* TODO: Do we need to set DMCUB_MEM_UNIT_ID? */
+ REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0);
+}
+
+void dmub_dcn42_backdoor_load_zfb_mode(struct dmub_srv *dmub,
+ const struct dmub_window *cw0,
+ const struct dmub_window *cw1)
+{
+ union dmub_addr offset;
+
+ REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1);
+ offset = cw0->offset;
+ REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part);
+ REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part);
+ REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base);
+ REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0,
+ DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top,
+ DMCUB_REGION3_CW0_ENABLE, 1);
+ offset = cw1->offset;
+ REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part);
+ REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part);
+ REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base);
+ REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0,
+ DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top,
+ DMCUB_REGION3_CW1_ENABLE, 1);
+ REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID,
+ 0x20);
+}
+void dmub_dcn42_setup_windows(struct dmub_srv *dmub,
+ const struct dmub_window *cw2,
+ const struct dmub_window *cw3,
+ const struct dmub_window *cw4,
+ const struct dmub_window *cw5,
+ const struct dmub_window *cw6,
+ const struct dmub_window *region6)
+{
+ (void)cw2;
+ union dmub_addr offset;
+
+ offset = cw3->offset;
+
+ REG_WRITE(DMCUB_REGION3_CW3_OFFSET, offset.u.low_part);
+ REG_WRITE(DMCUB_REGION3_CW3_OFFSET_HIGH, offset.u.high_part);
+ REG_WRITE(DMCUB_REGION3_CW3_BASE_ADDRESS, cw3->region.base);
+ REG_SET_2(DMCUB_REGION3_CW3_TOP_ADDRESS, 0,
+ DMCUB_REGION3_CW3_TOP_ADDRESS, cw3->region.top,
+ DMCUB_REGION3_CW3_ENABLE, 1);
+
+ offset = cw4->offset;
+
+ REG_WRITE(DMCUB_REGION3_CW4_OFFSET, offset.u.low_part);
+ REG_WRITE(DMCUB_REGION3_CW4_OFFSET_HIGH, offset.u.high_part);
+ REG_WRITE(DMCUB_REGION3_CW4_BASE_ADDRESS, cw4->region.base);
+ REG_SET_2(DMCUB_REGION3_CW4_TOP_ADDRESS, 0,
+ DMCUB_REGION3_CW4_TOP_ADDRESS, cw4->region.top,
+ DMCUB_REGION3_CW4_ENABLE, 1);
+
+ offset = cw5->offset;
+
+ REG_WRITE(DMCUB_REGION3_CW5_OFFSET, offset.u.low_part);
+ REG_WRITE(DMCUB_REGION3_CW5_OFFSET_HIGH, offset.u.high_part);
+ REG_WRITE(DMCUB_REGION3_CW5_BASE_ADDRESS, cw5->region.base);
+ REG_SET_2(DMCUB_REGION3_CW5_TOP_ADDRESS, 0,
+ DMCUB_REGION3_CW5_TOP_ADDRESS, cw5->region.top,
+ DMCUB_REGION3_CW5_ENABLE, 1);
+
+ REG_WRITE(DMCUB_REGION5_OFFSET, offset.u.low_part);
+ REG_WRITE(DMCUB_REGION5_OFFSET_HIGH, offset.u.high_part);
+ REG_SET_2(DMCUB_REGION5_TOP_ADDRESS, 0,
+ DMCUB_REGION5_TOP_ADDRESS,
+ cw5->region.top - cw5->region.base - 1,
+ DMCUB_REGION5_ENABLE, 1);
+
+ offset = cw6->offset;
+
+ REG_WRITE(DMCUB_REGION3_CW6_OFFSET, offset.u.low_part);
+ REG_WRITE(DMCUB_REGION3_CW6_OFFSET_HIGH, offset.u.high_part);
+ REG_WRITE(DMCUB_REGION3_CW6_BASE_ADDRESS, cw6->region.base);
+ REG_SET_2(DMCUB_REGION3_CW6_TOP_ADDRESS, 0,
+ DMCUB_REGION3_CW6_TOP_ADDRESS, cw6->region.top,
+ DMCUB_REGION3_CW6_ENABLE, 1);
+
+ offset = region6->offset;
+
+ REG_WRITE(DMCUB_REGION6_OFFSET, offset.u.low_part);
+ REG_WRITE(DMCUB_REGION6_OFFSET_HIGH, offset.u.high_part);
+ REG_SET_2(DMCUB_REGION6_TOP_ADDRESS, 0,
+ DMCUB_REGION6_TOP_ADDRESS,
+ region6->region.top - region6->region.base - 1,
+ DMCUB_REGION6_ENABLE, 1);
+}
+
+uint32_t dmub_dcn42_get_inbox1_wptr(struct dmub_srv *dmub)
+{
+ return REG_READ(DMCUB_INBOX1_WPTR);
+}
+
+uint32_t dmub_dcn42_get_inbox1_rptr(struct dmub_srv *dmub)
+{
+ return REG_READ(DMCUB_INBOX1_RPTR);
+}
+
+void dmub_dcn42_setup_out_mailbox(struct dmub_srv *dmub,
+ const struct dmub_region *outbox1)
+{
+ REG_WRITE(DMCUB_OUTBOX1_BASE_ADDRESS, outbox1->base);
+ REG_WRITE(DMCUB_OUTBOX1_SIZE, outbox1->top - outbox1->base);
+}
+
+uint32_t dmub_dcn42_get_outbox1_wptr(struct dmub_srv *dmub)
+{
+ /**
+ * outbox1 wptr register is accessed without locks (dal & dc)
+ * and to be called only by dmub_srv_stat_get_notification()
+ */
+ return REG_READ(DMCUB_OUTBOX1_WPTR);
+}
+
+void dmub_dcn42_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
+{
+ /**
+ * outbox1 rptr register is accessed without locks (dal & dc)
+ * and to be called only by dmub_srv_stat_get_notification()
+ */
+ REG_WRITE(DMCUB_OUTBOX1_RPTR, rptr_offset);
+}
+
+bool dmub_dcn42_is_supported(struct dmub_srv *dmub)
+{
+ // DCN without DMUB is not a supported configuration; safe to assume that it is always
+ // present.
+ return true;
+}
+
+union dmub_fw_boot_options dmub_dcn42_get_fw_boot_option(struct dmub_srv *dmub)
+{
+ union dmub_fw_boot_options option;
+
+ option.all = REG_READ(DMCUB_SCRATCH14);
+ return option;
+}
+
+void dmub_dcn42_setup_outbox0(struct dmub_srv *dmub,
+ const struct dmub_region *outbox0)
+{
+ REG_WRITE(DMCUB_OUTBOX0_BASE_ADDRESS, outbox0->base);
+
+ REG_WRITE(DMCUB_OUTBOX0_SIZE, outbox0->top - outbox0->base);
+}
+
+bool dmub_dcn42_should_detect(struct dmub_srv *dmub)
+{
+ uint32_t fw_boot_status = REG_READ(DMCUB_SCRATCH0);
+ bool should_detect = (fw_boot_status & DMUB_FW_BOOT_STATUS_BIT_DETECTION_REQUIRED) != 0;
+ return should_detect;
+}
+
+void dmub_dcn42_send_inbox0_cmd(struct dmub_srv *dmub, union dmub_inbox0_data_register data)
+{
+ REG_WRITE(DMCUB_INBOX0_WPTR, data.inbox0_cmd_common.all);
+}
+
+uint32_t dmub_dcn42_read_inbox0_ack_register(struct dmub_srv *dmub)
+{
+ return REG_READ(DMCUB_SCRATCH17);
+}
+
+bool dmub_dcn42_is_hw_powered_up(struct dmub_srv *dmub)
+{
+ union dmub_fw_boot_status status;
+ uint32_t is_enable;
+
+ REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enable);
+ if (is_enable == 0)
+ return false;
+
+ status.all = REG_READ(DMCUB_SCRATCH0);
+
+ return (status.bits.dal_fw && status.bits.hw_power_init_done && status.bits.mailbox_rdy) ||
+ (!status.bits.dal_fw && status.bits.mailbox_rdy);
+}
+
+void dmub_dcn42_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset)
+{
+ REG_WRITE(DMCUB_INBOX1_WPTR, wptr_offset);
+}
+
+bool dmub_dcn42_is_hw_init(struct dmub_srv *dmub)
+{
+ union dmub_fw_boot_status status;
+ uint32_t is_hw_init;
+
+ status.all = REG_READ(DMCUB_SCRATCH0);
+ REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_hw_init);
+
+ return is_hw_init != 0 && status.bits.dal_fw;
+}
+
+union dmub_fw_boot_status dmub_dcn42_get_fw_boot_status(struct dmub_srv *dmub)
+{
+ union dmub_fw_boot_status status;
+
+ status.all = REG_READ(DMCUB_SCRATCH0);
+ return status;
+}
+
+void dmub_dcn42_skip_dmub_panel_power_sequence(struct dmub_srv *dmub, bool skip)
+{
+ union dmub_fw_boot_options boot_options;
+ boot_options.all = REG_READ(DMCUB_SCRATCH14);
+ boot_options.bits.skip_phy_init_panel_sequence = skip;
+ REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
+}
+
+void dmub_dcn42_configure_dmub_in_system_memory(struct dmub_srv *dmub)
+{
+ /* DMCUB_REGION3_TMR_AXI_SPACE values:
+ * 0b011 (0x3) - FB physical address
+ * 0b100 (0x4) - GPU virtual address
+ *
+ * Default value is 0x3 (FB Physical address for TMR). When programming
+ * DMUB to be in system memory, change to 0x4. The system memory allocated
+ * is accessible by both GPU and CPU, so we use GPU virtual address.
+ */
+ REG_WRITE(DMCUB_REGION3_TMR_AXI_SPACE, 0x4);
+}
+
+void dmub_dcn42_clear_inbox0_ack_register(struct dmub_srv *dmub)
+{
+ REG_WRITE(DMCUB_SCRATCH17, 0);
+}
+
+void dmub_dcn42_send_reg_inbox0_cmd_msg(struct dmub_srv *dmub,
+ union dmub_rb_cmd *cmd)
+{
+ uint32_t *dwords = (uint32_t *)cmd;
+ int32_t payload_size_bytes = cmd->cmd_common.header.payload_bytes;
+ uint32_t msg_index;
+ static_assert(sizeof(*cmd) == 64, "DMUB command size mismatch");
+
+ /* read remaining data based on payload size */
+ for (msg_index = 0; msg_index < 15; msg_index++) {
+ if (payload_size_bytes <= msg_index * 4) {
+ break;
+ }
+
+ switch (msg_index) {
+ case 0:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG0, dwords[msg_index + 1]);
+ break;
+ case 1:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG1, dwords[msg_index + 1]);
+ break;
+ case 2:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG2, dwords[msg_index + 1]);
+ break;
+ case 3:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG3, dwords[msg_index + 1]);
+ break;
+ case 4:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG4, dwords[msg_index + 1]);
+ break;
+ case 5:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG5, dwords[msg_index + 1]);
+ break;
+ case 6:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG6, dwords[msg_index + 1]);
+ break;
+ case 7:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG7, dwords[msg_index + 1]);
+ break;
+ case 8:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG8, dwords[msg_index + 1]);
+ break;
+ case 9:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG9, dwords[msg_index + 1]);
+ break;
+ case 10:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG10, dwords[msg_index + 1]);
+ break;
+ case 11:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG11, dwords[msg_index + 1]);
+ break;
+ case 12:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG12, dwords[msg_index + 1]);
+ break;
+ case 13:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG13, dwords[msg_index + 1]);
+ break;
+ case 14:
+ REG_WRITE(DMCUB_REG_INBOX0_MSG14, dwords[msg_index + 1]);
+ break;
+ }
+ }
+
+ /* writing to INBOX RDY register will trigger DMUB REG INBOX0 RDY
+ * interrupt.
+ */
+ REG_WRITE(DMCUB_REG_INBOX0_RDY, dwords[0]);
+}
+
+uint32_t dmub_dcn42_read_reg_inbox0_rsp_int_status(struct dmub_srv *dmub)
+{
+ uint32_t status;
+
+ REG_GET(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_STAT, &status);
+ return status;
+}
+
+void dmub_dcn42_read_reg_inbox0_cmd_rsp(struct dmub_srv *dmub,
+ union dmub_rb_cmd *cmd)
+{
+ uint32_t *dwords = (uint32_t *)cmd;
+
+ static_assert(sizeof(*cmd) == 64, "DMUB command size mismatch");
+
+ dwords[0] = REG_READ(DMCUB_REG_INBOX0_RSP);
+ dwords[1] = REG_READ(DMCUB_REG_INBOX0_MSG0);
+ dwords[2] = REG_READ(DMCUB_REG_INBOX0_MSG1);
+ dwords[3] = REG_READ(DMCUB_REG_INBOX0_MSG2);
+ dwords[4] = REG_READ(DMCUB_REG_INBOX0_MSG3);
+ dwords[5] = REG_READ(DMCUB_REG_INBOX0_MSG4);
+ dwords[6] = REG_READ(DMCUB_REG_INBOX0_MSG5);
+ dwords[7] = REG_READ(DMCUB_REG_INBOX0_MSG6);
+ dwords[8] = REG_READ(DMCUB_REG_INBOX0_MSG7);
+ dwords[9] = REG_READ(DMCUB_REG_INBOX0_MSG8);
+ dwords[10] = REG_READ(DMCUB_REG_INBOX0_MSG9);
+ dwords[11] = REG_READ(DMCUB_REG_INBOX0_MSG10);
+ dwords[12] = REG_READ(DMCUB_REG_INBOX0_MSG11);
+ dwords[13] = REG_READ(DMCUB_REG_INBOX0_MSG12);
+ dwords[14] = REG_READ(DMCUB_REG_INBOX0_MSG13);
+ dwords[15] = REG_READ(DMCUB_REG_INBOX0_MSG14);
+}
+
+void dmub_dcn42_write_reg_inbox0_rsp_int_ack(struct dmub_srv *dmub)
+{
+ REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_ACK, 1);
+}
+
+void dmub_dcn42_clear_reg_inbox0_rsp_int_ack(struct dmub_srv *dmub)
+{
+ REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_ACK, 0);
+}
+
+void dmub_dcn42_enable_reg_inbox0_rsp_int(struct dmub_srv *dmub, bool enable)
+{
+ REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_EN, enable ? 1:0);
+}
+
+void dmub_dcn42_write_reg_outbox0_rdy_int_ack(struct dmub_srv *dmub)
+{
+ REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK, 1);
+ REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK, 0);
+}
+
+void dmub_dcn42_read_reg_outbox0_msg(struct dmub_srv *dmub, uint32_t *msg)
+{
+ *msg = REG_READ(DMCUB_REG_OUTBOX0_MSG0);
+}
+
+
+void dmub_dcn42_enable_reg_outbox0_rdy_int(struct dmub_srv *dmub, bool enable)
+{
+ REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN, enable ? 1:0);
+}
+
+uint32_t dmub_dcn42_read_reg_outbox0_rdy_int_status(struct dmub_srv *dmub)
+{
+ uint32_t status;
+
+ REG_GET(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_STAT, &status);
+ return status;
+}
+
+void dmub_dcn42_setup_mailbox(struct dmub_srv *dmub,
+ const struct dmub_region *inbox1)
+{
+ REG_WRITE(DMCUB_INBOX1_BASE_ADDRESS, inbox1->base);
+ REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
+}
+
+void dmub_dcn42_set_gpint(struct dmub_srv *dmub,
+ union dmub_gpint_data_register reg)
+{
+ REG_WRITE(DMCUB_GPINT_DATAIN1, reg.all);
+}
+
+bool dmub_dcn42_is_gpint_acked(struct dmub_srv *dmub,
+ union dmub_gpint_data_register reg)
+{
+ union dmub_gpint_data_register test;
+
+ reg.bits.status = 0;
+ test.all = REG_READ(DMCUB_GPINT_DATAIN1);
+
+ return test.all == reg.all;
+}
+
+uint32_t dmub_dcn42_get_gpint_response(struct dmub_srv *dmub)
+{
+ return REG_READ(DMCUB_SCRATCH7);
+}
+
+uint32_t dmub_dcn42_get_gpint_dataout(struct dmub_srv *dmub)
+{
+ uint32_t dataout = REG_READ(DMCUB_GPINT_DATAOUT);
+
+ REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 0);
+
+ REG_WRITE(DMCUB_GPINT_DATAOUT, 0);
+ REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 1);
+ REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 0);
+
+ REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 1);
+
+ return dataout;
+}
+
+uint32_t dmub_dcn42_get_outbox0_wptr(struct dmub_srv *dmub)
+{
+ return REG_READ(DMCUB_OUTBOX0_WPTR);
+}
+
+void dmub_dcn42_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
+{
+ REG_WRITE(DMCUB_OUTBOX0_RPTR, rptr_offset);
+}
+
+uint32_t dmub_dcn42_get_current_time(struct dmub_srv *dmub)
+{
+ return REG_READ(DMCUB_TIMER_CURRENT);
+}
+
+void dmub_dcn42_get_diagnostic_data(struct dmub_srv *dmub)
+{
+ uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset, is_pwait;
+ uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled;
+ struct dmub_timeout_info timeout = {0};
+
+ if (!dmub)
+ return;
+
+ /* timeout data filled externally, cache before resetting memory */
+ timeout = dmub->debug.timeout_info;
+ memset(&dmub->debug, 0, sizeof(dmub->debug));
+ dmub->debug.timeout_info = timeout;
+
+ dmub->debug.dmcub_version = dmub->fw_version;
+
+ dmub->debug.scratch[0] = REG_READ(DMCUB_SCRATCH0);
+ dmub->debug.scratch[1] = REG_READ(DMCUB_SCRATCH1);
+ dmub->debug.scratch[2] = REG_READ(DMCUB_SCRATCH2);
+ dmub->debug.scratch[3] = REG_READ(DMCUB_SCRATCH3);
+ dmub->debug.scratch[4] = REG_READ(DMCUB_SCRATCH4);
+ dmub->debug.scratch[5] = REG_READ(DMCUB_SCRATCH5);
+ dmub->debug.scratch[6] = REG_READ(DMCUB_SCRATCH6);
+ dmub->debug.scratch[7] = REG_READ(DMCUB_SCRATCH7);
+ dmub->debug.scratch[8] = REG_READ(DMCUB_SCRATCH8);
+ dmub->debug.scratch[9] = REG_READ(DMCUB_SCRATCH9);
+ dmub->debug.scratch[10] = REG_READ(DMCUB_SCRATCH10);
+ dmub->debug.scratch[11] = REG_READ(DMCUB_SCRATCH11);
+ dmub->debug.scratch[12] = REG_READ(DMCUB_SCRATCH12);
+ dmub->debug.scratch[13] = REG_READ(DMCUB_SCRATCH13);
+ dmub->debug.scratch[14] = REG_READ(DMCUB_SCRATCH14);
+ dmub->debug.scratch[15] = REG_READ(DMCUB_SCRATCH15);
+ dmub->debug.scratch[16] = REG_READ(DMCUB_SCRATCH16);
+
+ dmub->debug.undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR);
+ dmub->debug.inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR);
+ dmub->debug.data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR);
+
+ dmub->debug.inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR);
+ dmub->debug.inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR);
+ dmub->debug.inbox1_size = REG_READ(DMCUB_INBOX1_SIZE);
+
+ dmub->debug.inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR);
+ dmub->debug.inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR);
+ dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE);
+
+ dmub->debug.outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR);
+ dmub->debug.outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR);
+ dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE);
+
+ REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
+ ASSERT(is_dmub_enabled <= 0xFF);
+ dmub->debug.is_dmcub_enabled = (uint8_t)is_dmub_enabled;
+
+ REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait);
+ ASSERT(is_pwait <= 0xFF);
+ dmub->debug.is_pwait = (uint8_t)is_pwait;
+
+ REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
+ ASSERT(is_soft_reset <= 0xFF);
+ dmub->debug.is_dmcub_soft_reset = (uint8_t)is_soft_reset;
+
+ REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
+ ASSERT(is_sec_reset <= 0xFF);
+ dmub->debug.is_dmcub_secure_reset = (uint8_t)is_sec_reset;
+
+ REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
+ ASSERT(is_traceport_enabled <= 0xFF);
+ dmub->debug.is_traceport_en = (uint8_t)is_traceport_enabled;
+
+ REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
+ ASSERT(is_cw0_enabled <= 0xFF);
+ dmub->debug.is_cw0_enabled = (uint8_t)is_cw0_enabled;
+
+ REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
+ ASSERT(is_cw6_enabled <= 0xFF);
+ dmub->debug.is_cw6_enabled = (uint8_t)is_cw6_enabled;
+
+ dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0);
+}
+
+bool dmub_dcn42_get_preos_fw_info(struct dmub_srv *dmub)
+{
+ uint64_t region3_cw5_offset;
+ uint32_t top_addr, top_addr_enable, offset_low;
+ uint32_t offset_high, base_addr, fw_version;
+ bool is_vbios_fw = false;
+
+ memset(&dmub->preos_info, 0, sizeof(dmub->preos_info));
+
+ fw_version = REG_READ(DMCUB_SCRATCH1);
+ is_vbios_fw = ((fw_version >> 6) & 0x01) ? true : false;
+ if (!is_vbios_fw)
+ return false;
+
+ dmub->preos_info.boot_status = REG_READ(DMCUB_SCRATCH0);
+ dmub->preos_info.fw_version = REG_READ(DMCUB_SCRATCH1);
+ dmub->preos_info.boot_options = REG_READ(DMCUB_SCRATCH14);
+ REG_GET(DMCUB_REGION3_CW5_TOP_ADDRESS,
+ DMCUB_REGION3_CW5_ENABLE, &top_addr_enable);
+ if (top_addr_enable) {
+ dmub_dcn42_get_fb_base_offset(dmub,
+ &dmub->preos_info.fb_base, &dmub->preos_info.fb_offset);
+ offset_low = REG_READ(DMCUB_REGION3_CW5_OFFSET);
+ offset_high = REG_READ(DMCUB_REGION3_CW5_OFFSET_HIGH);
+ region3_cw5_offset = ((uint64_t)offset_high << 32) | offset_low;
+ dmub->preos_info.trace_buffer_phy_addr = region3_cw5_offset
+ - dmub->preos_info.fb_base + dmub->preos_info.fb_offset;
+
+ REG_GET(DMCUB_REGION3_CW5_TOP_ADDRESS,
+ DMCUB_REGION3_CW5_TOP_ADDRESS, &top_addr);
+ base_addr = REG_READ(DMCUB_REGION3_CW5_BASE_ADDRESS) & 0x1FFFFFFF;
+ dmub->preos_info.trace_buffer_size =
+ (top_addr > base_addr) ? (top_addr - base_addr + 1) : 0;
+ }
+
+ return true;
+}
+
+void dmub_dcn42_write_reg_outbox0_rsp(struct dmub_srv *dmub, uint32_t *rsp)
+{
+ REG_WRITE(DMCUB_REG_OUTBOX0_RSP, *rsp);
+}
+
+uint32_t dmub_dcn42_read_reg_outbox0_rsp_int_status(struct dmub_srv *dmub)
+{
+ uint32_t status;
+
+ REG_GET(DMCUB_INTERRUPT_STATUS, DMCUB_REG_OUTBOX0_RSP_INT_STAT, &status);
+ return status;
+}
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h
new file mode 100644
index 000000000000..c53f7691d1a8
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn42.h
@@ -0,0 +1,303 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _DMUB_DCN42_H_
+#define _DMUB_DCN42_H_
+
+#include "dmub_dcn35.h"
+#include "dmub_dcn401.h"
+
+
+struct dmub_srv;
+
+/* DCN42 register definitions. */
+
+#define DMUB_DCN42_REGS() \
+ DMUB_SR(DMCUB_CNTL) \
+ DMUB_SR(DMCUB_CNTL2) \
+ DMUB_SR(DMCUB_SEC_CNTL) \
+ DMUB_SR(DMCUB_INBOX0_SIZE) \
+ DMUB_SR(DMCUB_INBOX0_RPTR) \
+ DMUB_SR(DMCUB_INBOX0_WPTR) \
+ DMUB_SR(DMCUB_INBOX1_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_INBOX1_SIZE) \
+ DMUB_SR(DMCUB_INBOX1_RPTR) \
+ DMUB_SR(DMCUB_INBOX1_WPTR) \
+ DMUB_SR(DMCUB_OUTBOX0_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_OUTBOX0_SIZE) \
+ DMUB_SR(DMCUB_OUTBOX0_RPTR) \
+ DMUB_SR(DMCUB_OUTBOX0_WPTR) \
+ DMUB_SR(DMCUB_OUTBOX1_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_OUTBOX1_SIZE) \
+ DMUB_SR(DMCUB_OUTBOX1_RPTR) \
+ DMUB_SR(DMCUB_OUTBOX1_WPTR) \
+ DMUB_SR(DMCUB_REGION3_CW0_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW1_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW2_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW3_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW4_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW5_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW6_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW7_OFFSET) \
+ DMUB_SR(DMCUB_REGION3_CW0_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW1_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW2_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW3_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW4_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW5_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW6_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW7_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION3_CW0_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW1_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW2_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW3_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW4_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW5_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW6_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW7_BASE_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW0_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW1_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW2_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW3_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW4_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW5_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW6_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION3_CW7_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION4_OFFSET) \
+ DMUB_SR(DMCUB_REGION4_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION4_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION5_OFFSET) \
+ DMUB_SR(DMCUB_REGION5_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION5_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_REGION6_OFFSET) \
+ DMUB_SR(DMCUB_REGION6_OFFSET_HIGH) \
+ DMUB_SR(DMCUB_REGION6_TOP_ADDRESS) \
+ DMUB_SR(DMCUB_SCRATCH0) \
+ DMUB_SR(DMCUB_SCRATCH1) \
+ DMUB_SR(DMCUB_SCRATCH2) \
+ DMUB_SR(DMCUB_SCRATCH3) \
+ DMUB_SR(DMCUB_SCRATCH4) \
+ DMUB_SR(DMCUB_SCRATCH5) \
+ DMUB_SR(DMCUB_SCRATCH6) \
+ DMUB_SR(DMCUB_SCRATCH7) \
+ DMUB_SR(DMCUB_SCRATCH8) \
+ DMUB_SR(DMCUB_SCRATCH9) \
+ DMUB_SR(DMCUB_SCRATCH10) \
+ DMUB_SR(DMCUB_SCRATCH11) \
+ DMUB_SR(DMCUB_SCRATCH12) \
+ DMUB_SR(DMCUB_SCRATCH13) \
+ DMUB_SR(DMCUB_SCRATCH14) \
+ DMUB_SR(DMCUB_SCRATCH15) \
+ DMUB_SR(DMCUB_SCRATCH16) \
+ DMUB_SR(DMCUB_SCRATCH17) \
+ DMUB_SR(DMCUB_SCRATCH18) \
+ DMUB_SR(DMCUB_SCRATCH19) \
+ DMUB_SR(DMCUB_SCRATCH20) \
+ DMUB_SR(DMCUB_SCRATCH21) \
+ DMUB_SR(DMCUB_GPINT_DATAIN0) \
+ DMUB_SR(DMCUB_GPINT_DATAIN1) \
+ DMUB_SR(DMCUB_GPINT_DATAOUT) \
+ DMUB_SR(MMHUBBUB_SOFT_RESET) \
+ DMUB_SR(DCN_VM_FB_LOCATION_BASE) \
+ DMUB_SR(DCN_VM_FB_OFFSET) \
+ DMUB_SR(DMCUB_TIMER_CURRENT) \
+ DMUB_SR(DMCUB_INST_FETCH_FAULT_ADDR) \
+ DMUB_SR(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR) \
+ DMUB_SR(DMCUB_DATA_WRITE_FAULT_ADDR) \
+ DMUB_SR(DMCUB_REGION3_TMR_AXI_SPACE) \
+ DMUB_SR(DMCUB_INTERRUPT_ENABLE) \
+ DMUB_SR(DMCUB_INTERRUPT_ACK) \
+ DMUB_SR(DMU_CLK_CNTL) \
+ DMUB_SR(DMCUB_INTERRUPT_STATUS) \
+ DMUB_SR(DMCUB_REG_INBOX0_RDY) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG0) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG1) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG2) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG3) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG4) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG5) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG6) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG7) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG8) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG9) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG10) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG11) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG12) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG13) \
+ DMUB_SR(DMCUB_REG_INBOX0_MSG14) \
+ DMUB_SR(DMCUB_REG_INBOX0_RSP) \
+ DMUB_SR(DMCUB_REG_OUTBOX0_RDY) \
+ DMUB_SR(DMCUB_REG_OUTBOX0_MSG0) \
+ DMUB_SR(DMCUB_REG_OUTBOX0_RSP) \
+ DMUB_SR(HOST_INTERRUPT_CSR)
+
+#define DMUB_DCN42_FIELDS() \
+ DMUB_SF(DMCUB_CNTL, DMCUB_ENABLE) \
+ DMUB_SF(DMCUB_CNTL, DMCUB_TRACEPORT_EN) \
+ DMUB_SF(DMCUB_CNTL2, DMCUB_SOFT_RESET) \
+ DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET) \
+ DMUB_SF(DMCUB_SEC_CNTL, DMCUB_MEM_UNIT_ID) \
+ DMUB_SF(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS) \
+ DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW1_TOP_ADDRESS, DMCUB_REGION3_CW1_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW2_TOP_ADDRESS, DMCUB_REGION3_CW2_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW2_TOP_ADDRESS, DMCUB_REGION3_CW2_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW3_TOP_ADDRESS, DMCUB_REGION3_CW3_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW3_TOP_ADDRESS, DMCUB_REGION3_CW3_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW4_TOP_ADDRESS, DMCUB_REGION3_CW4_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW4_TOP_ADDRESS, DMCUB_REGION3_CW4_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW5_TOP_ADDRESS, DMCUB_REGION3_CW5_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW5_TOP_ADDRESS, DMCUB_REGION3_CW5_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE) \
+ DMUB_SF(DMCUB_REGION3_CW7_TOP_ADDRESS, DMCUB_REGION3_CW7_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION3_CW7_TOP_ADDRESS, DMCUB_REGION3_CW7_ENABLE) \
+ DMUB_SF(DMCUB_REGION4_TOP_ADDRESS, DMCUB_REGION4_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION4_TOP_ADDRESS, DMCUB_REGION4_ENABLE) \
+ DMUB_SF(DMCUB_REGION5_TOP_ADDRESS, DMCUB_REGION5_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION5_TOP_ADDRESS, DMCUB_REGION5_ENABLE) \
+ DMUB_SF(DMCUB_REGION6_TOP_ADDRESS, DMCUB_REGION6_TOP_ADDRESS) \
+ DMUB_SF(DMCUB_REGION6_TOP_ADDRESS, DMCUB_REGION6_ENABLE) \
+ DMUB_SF(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET) \
+ DMUB_SF(DCN_VM_FB_LOCATION_BASE, FB_BASE) \
+ DMUB_SF(DCN_VM_FB_OFFSET, FB_OFFSET) \
+ DMUB_SF(DMCUB_INBOX0_WPTR, DMCUB_INBOX0_WPTR) \
+ DMUB_SF(DMCUB_REGION3_TMR_AXI_SPACE, DMCUB_REGION3_TMR_AXI_SPACE) \
+ DMUB_SF(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN) \
+ DMUB_SF(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK) \
+ DMUB_SF(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS) \
+ DMUB_SF(DMU_CLK_CNTL, LONO_DISPCLK_GATE_DISABLE) \
+ DMUB_SF(DMU_CLK_CNTL, LONO_SOCCLK_GATE_DISABLE) \
+ DMUB_SF(DMU_CLK_CNTL, LONO_DMCUBCLK_GATE_DISABLE) \
+ DMUB_SF(DMCUB_INTERRUPT_STATUS, DMCUB_REG_OUTBOX0_RSP_INT_STAT) \
+ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_ACK) \
+ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_STAT) \
+ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_EN) \
+ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK) \
+ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_STAT) \
+ DMUB_SF(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN)
+
+struct dmub_srv_dcn42_reg_offset {
+#define DMUB_SR(reg) uint32_t reg;
+ DMUB_DCN42_REGS()
+ DMCUB_INTERNAL_REGS()
+#undef DMUB_SR
+};
+
+struct dmub_srv_dcn42_reg_shift {
+#define DMUB_SF(reg, field) uint8_t reg##__##field;
+ DMUB_DCN42_FIELDS()
+#undef DMUB_SF
+};
+
+struct dmub_srv_dcn42_reg_mask {
+#define DMUB_SF(reg, field) uint32_t reg##__##field;
+ DMUB_DCN42_FIELDS()
+#undef DMUB_SF
+};
+
+struct dmub_srv_dcn42_regs {
+ struct dmub_srv_dcn42_reg_offset offset;
+ struct dmub_srv_dcn42_reg_mask mask;
+ struct dmub_srv_dcn42_reg_shift shift;
+};
+
+/* Function declarations */
+
+/* Initialization and configuration */
+void dmub_srv_dcn42_regs_init(struct dmub_srv *dmub, struct dc_context *ctx);
+void dmub_dcn42_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params);
+void dmub_dcn42_skip_dmub_panel_power_sequence(struct dmub_srv *dmub, bool skip);
+void dmub_dcn42_configure_dmub_in_system_memory(struct dmub_srv *dmub);
+
+/* Reset and control */
+void dmub_dcn42_reset(struct dmub_srv *dmub);
+void dmub_dcn42_reset_release(struct dmub_srv *dmub);
+
+/* Firmware loading */
+void dmub_dcn42_backdoor_load(struct dmub_srv *dmub, const struct dmub_window *cw0, const struct dmub_window *cw1);
+void dmub_dcn42_backdoor_load_zfb_mode(struct dmub_srv *dmub, const struct dmub_window *cw0, const struct dmub_window *cw1);
+void dmub_dcn42_setup_windows(struct dmub_srv *dmub, const struct dmub_window *cw2, const struct dmub_window *cw3, const struct dmub_window *cw4, const struct dmub_window *cw5, const struct dmub_window *cw6, const struct dmub_window *region6);
+
+/* Mailbox operations - Inbox1 */
+void dmub_dcn42_setup_mailbox(struct dmub_srv *dmub, const struct dmub_region *inbox1);
+uint32_t dmub_dcn42_get_inbox1_wptr(struct dmub_srv *dmub);
+uint32_t dmub_dcn42_get_inbox1_rptr(struct dmub_srv *dmub);
+void dmub_dcn42_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset);
+
+/* Mailbox operations - Outbox1 */
+void dmub_dcn42_setup_out_mailbox(struct dmub_srv *dmub, const struct dmub_region *outbox1);
+uint32_t dmub_dcn42_get_outbox1_wptr(struct dmub_srv *dmub);
+void dmub_dcn42_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset);
+
+/* Mailbox operations - Outbox0 */
+void dmub_dcn42_setup_outbox0(struct dmub_srv *dmub, const struct dmub_region *outbox0);
+uint32_t dmub_dcn42_get_outbox0_wptr(struct dmub_srv *dmub);
+void dmub_dcn42_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset);
+
+/* Mailbox operations - Inbox0 */
+void dmub_dcn42_send_inbox0_cmd(struct dmub_srv *dmub, union dmub_inbox0_data_register data);
+void dmub_dcn42_clear_inbox0_ack_register(struct dmub_srv *dmub);
+uint32_t dmub_dcn42_read_inbox0_ack_register(struct dmub_srv *dmub);
+
+/* REG Inbox0/Outbox0 operations */
+void dmub_dcn42_send_reg_inbox0_cmd_msg(struct dmub_srv *dmub, union dmub_rb_cmd *cmd);
+uint32_t dmub_dcn42_read_reg_inbox0_rsp_int_status(struct dmub_srv *dmub);
+void dmub_dcn42_read_reg_inbox0_cmd_rsp(struct dmub_srv *dmub, union dmub_rb_cmd *cmd);
+void dmub_dcn42_write_reg_inbox0_rsp_int_ack(struct dmub_srv *dmub);
+void dmub_dcn42_clear_reg_inbox0_rsp_int_ack(struct dmub_srv *dmub);
+void dmub_dcn42_enable_reg_inbox0_rsp_int(struct dmub_srv *dmub, bool enable);
+
+void dmub_dcn42_write_reg_outbox0_rdy_int_ack(struct dmub_srv *dmub);
+void dmub_dcn42_read_reg_outbox0_msg(struct dmub_srv *dmub, uint32_t *msg);
+void dmub_dcn42_write_reg_outbox0_rsp(struct dmub_srv *dmub, uint32_t *rsp);
+uint32_t dmub_dcn42_read_reg_outbox0_rsp_int_status(struct dmub_srv *dmub);
+void dmub_dcn42_enable_reg_outbox0_rdy_int(struct dmub_srv *dmub, bool enable);
+uint32_t dmub_dcn42_read_reg_outbox0_rdy_int_status(struct dmub_srv *dmub);
+
+/* GPINT operations */
+void dmub_dcn42_set_gpint(struct dmub_srv *dmub, union dmub_gpint_data_register reg);
+bool dmub_dcn42_is_gpint_acked(struct dmub_srv *dmub, union dmub_gpint_data_register reg);
+uint32_t dmub_dcn42_get_gpint_response(struct dmub_srv *dmub);
+uint32_t dmub_dcn42_get_gpint_dataout(struct dmub_srv *dmub);
+
+/* Status and detection */
+bool dmub_dcn42_is_hw_init(struct dmub_srv *dmub);
+bool dmub_dcn42_is_supported(struct dmub_srv *dmub);
+bool dmub_dcn42_is_hw_powered_up(struct dmub_srv *dmub);
+bool dmub_dcn42_should_detect(struct dmub_srv *dmub);
+
+
+/* Firmware boot status and options */
+union dmub_fw_boot_status dmub_dcn42_get_fw_boot_status(struct dmub_srv *dmub);
+union dmub_fw_boot_options dmub_dcn42_get_fw_boot_option(struct dmub_srv *dmub);
+
+/* Timing and diagnostics */
+uint32_t dmub_dcn42_get_current_time(struct dmub_srv *dmub);
+void dmub_dcn42_get_diagnostic_data(struct dmub_srv *dmub);
+bool dmub_dcn42_get_preos_fw_info(struct dmub_srv *dmub);
+
+#endif /* _DMUB_DCN42_H_ */
diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c
index ca0c8a54b635..b5566ef8d4f3 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_reg.c
@@ -45,6 +45,7 @@ static void set_reg_field_values(struct dmub_reg_value_masks *field_value_mask,
uint32_t mask1, uint32_t field_value1,
va_list ap)
{
+ (void)addr;
uint32_t shift, mask, field_value;
int i = 1;
@@ -57,8 +58,9 @@ static void set_reg_field_values(struct dmub_reg_value_masks *field_value_mask,
mask = va_arg(ap, uint32_t);
field_value = va_arg(ap, uint32_t);
+ ASSERT(shift <= 0xFF);
set_reg_field_value_masks(field_value_mask, field_value, mask,
- shift);
+ (uint8_t)shift);
i++;
}
}
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 83cf4888fb54..10d23f5f5d94 100644
--- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: MIT
/*
- * Copyright 2019 Advanced Micro Devices, Inc.
+ * Copyright 2019-2026 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -22,7 +23,6 @@
* Authors: AMD
*
*/
-
#include "../dmub_srv.h"
#include "dmub_dcn20.h"
#include "dmub_dcn21.h"
@@ -40,6 +40,7 @@
#include "dmub_dcn351.h"
#include "dmub_dcn36.h"
#include "dmub_dcn401.h"
+#include "dmub_dcn42.h"
#include "os_types.h"
/*
* Note: the DMUB service is standalone. No additional headers should be
@@ -87,6 +88,7 @@
static struct dmub_srv_dcn32_regs dmub_srv_dcn32_regs;
static struct dmub_srv_dcn35_regs dmub_srv_dcn35_regs;
+struct dmub_srv_dcn42_regs dmub_srv_dcn42_regs;
static inline uint32_t dmub_align(uint32_t val, uint32_t factor)
{
@@ -410,6 +412,64 @@ static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
funcs->is_hw_powered_up = dmub_dcn35_is_hw_powered_up;
funcs->should_detect = dmub_dcn35_should_detect;
break;
+ case DMUB_ASIC_DCN42:
+ dmub->regs_dcn42 = &dmub_srv_dcn42_regs;
+ funcs->configure_dmub_in_system_memory = dmub_dcn42_configure_dmub_in_system_memory;
+ funcs->send_inbox0_cmd = dmub_dcn42_send_inbox0_cmd;
+ funcs->clear_inbox0_ack_register = dmub_dcn42_clear_inbox0_ack_register;
+ funcs->read_inbox0_ack_register = dmub_dcn42_read_inbox0_ack_register;
+ funcs->reset = dmub_dcn42_reset;
+ funcs->reset_release = dmub_dcn42_reset_release;
+ funcs->backdoor_load = dmub_dcn42_backdoor_load;
+ funcs->backdoor_load_zfb_mode = dmub_dcn42_backdoor_load_zfb_mode;
+ funcs->setup_windows = dmub_dcn42_setup_windows;
+ funcs->setup_mailbox = dmub_dcn42_setup_mailbox;
+ funcs->get_inbox1_wptr = dmub_dcn42_get_inbox1_wptr;
+ funcs->get_inbox1_rptr = dmub_dcn42_get_inbox1_rptr;
+ funcs->set_inbox1_wptr = dmub_dcn42_set_inbox1_wptr;
+ funcs->setup_out_mailbox = dmub_dcn42_setup_out_mailbox;
+ funcs->get_outbox1_wptr = dmub_dcn42_get_outbox1_wptr;
+ funcs->set_outbox1_rptr = dmub_dcn42_set_outbox1_rptr;
+ funcs->is_supported = dmub_dcn42_is_supported;
+ funcs->is_hw_init = dmub_dcn42_is_hw_init;
+ funcs->set_gpint = dmub_dcn42_set_gpint;
+ funcs->is_gpint_acked = dmub_dcn42_is_gpint_acked;
+ funcs->get_gpint_response = dmub_dcn42_get_gpint_response;
+ funcs->get_gpint_dataout = dmub_dcn42_get_gpint_dataout;
+ funcs->get_fw_status = dmub_dcn42_get_fw_boot_status;
+ funcs->get_fw_boot_option = dmub_dcn42_get_fw_boot_option;
+ funcs->enable_dmub_boot_options = dmub_dcn42_enable_dmub_boot_options;
+ funcs->skip_dmub_panel_power_sequence = dmub_dcn42_skip_dmub_panel_power_sequence;
+ /*outbox0 call stacks*/
+ funcs->setup_outbox0 = dmub_dcn42_setup_outbox0;
+ funcs->get_outbox0_wptr = dmub_dcn42_get_outbox0_wptr;
+ funcs->set_outbox0_rptr = dmub_dcn42_set_outbox0_rptr;
+
+ funcs->get_current_time = dmub_dcn42_get_current_time;
+ funcs->get_diagnostic_data = dmub_dcn42_get_diagnostic_data;
+ funcs->get_preos_fw_info = dmub_dcn42_get_preos_fw_info;
+
+ /*carried from dcn401*/
+ funcs->send_reg_inbox0_cmd_msg = dmub_dcn42_send_reg_inbox0_cmd_msg;
+ funcs->read_reg_inbox0_rsp_int_status = dmub_dcn42_read_reg_inbox0_rsp_int_status;
+ funcs->read_reg_inbox0_cmd_rsp = dmub_dcn42_read_reg_inbox0_cmd_rsp;
+ funcs->write_reg_inbox0_rsp_int_ack = dmub_dcn42_write_reg_inbox0_rsp_int_ack;
+ funcs->clear_reg_inbox0_rsp_int_ack = dmub_dcn42_clear_reg_inbox0_rsp_int_ack;
+ funcs->enable_reg_inbox0_rsp_int = dmub_dcn42_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_dcn42_write_reg_outbox0_rdy_int_ack;
+ funcs->read_reg_outbox0_msg = dmub_dcn42_read_reg_outbox0_msg;
+ funcs->write_reg_outbox0_rsp = dmub_dcn42_write_reg_outbox0_rsp;
+ funcs->read_reg_outbox0_rdy_int_status = dmub_dcn42_read_reg_outbox0_rdy_int_status;
+ funcs->read_reg_outbox0_rsp_int_status = dmub_dcn42_read_reg_outbox0_rsp_int_status;
+ funcs->enable_reg_inbox0_rsp_int = dmub_dcn42_enable_reg_inbox0_rsp_int;
+ funcs->enable_reg_outbox0_rdy_int = dmub_dcn42_enable_reg_outbox0_rdy_int;
+ funcs->init_reg_offsets = dmub_srv_dcn42_regs_init;
+
+ funcs->is_hw_powered_up = dmub_dcn42_is_hw_powered_up;
+ funcs->should_detect = dmub_dcn42_should_detect;
+ break;
case DMUB_ASIC_DCN401:
dmub->regs_dcn401 = &dmub_srv_dcn401_regs;
@@ -974,8 +1034,8 @@ enum dmub_status dmub_srv_wait_for_auto_load(struct dmub_srv *dmub,
static void dmub_srv_update_reg_inbox0_status(struct dmub_srv *dmub)
{
if (dmub->reg_inbox0.is_pending) {
- dmub->reg_inbox0.is_pending = dmub->hw_funcs.read_reg_inbox0_rsp_int_status &&
- !dmub->hw_funcs.read_reg_inbox0_rsp_int_status(dmub);
+ dmub->reg_inbox0.is_pending = (dmub->hw_funcs.read_reg_inbox0_rsp_int_status &&
+ !dmub->hw_funcs.read_reg_inbox0_rsp_int_status(dmub)) != 0;
if (!dmub->reg_inbox0.is_pending) {
/* ack the rsp interrupt */
@@ -1260,7 +1320,7 @@ void dmub_srv_set_power_state(struct dmub_srv *dmub, enum dmub_srv_power_state_t
enum dmub_status dmub_srv_reg_cmd_execute(struct dmub_srv *dmub, union dmub_rb_cmd *cmd)
{
- uint32_t num_pending = 0;
+ uint64_t num_pending = 0;
if (!dmub->hw_init)
return DMUB_STATUS_INVALID;
@@ -1288,7 +1348,7 @@ enum dmub_status dmub_srv_reg_cmd_execute(struct dmub_srv *dmub, union dmub_rb_c
dmub->reg_inbox0.num_submitted++;
dmub->reg_inbox0.is_pending = true;
- dmub->reg_inbox0.is_multi_pending = cmd->cmd_common.header.multi_cmd_pending;
+ dmub->reg_inbox0.is_multi_pending = cmd->cmd_common.header.multi_cmd_pending != 0;
return DMUB_STATUS_OK;
}
diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h
index f40dc612ec73..b5d97b394131 100644
--- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h
+++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h
@@ -93,6 +93,8 @@ enum bp_external_encoder_control_action {
EXTERNAL_ENCODER_CONTROL_SETUP = 0xf,
EXTERNAL_ENCODER_CONTROL_UNBLANK = 0x10,
EXTERNAL_ENCODER_CONTROL_BLANK = 0x11,
+ EXTERNAL_ENCODER_CONTROL_DAC_LOAD_DETECT = 0x12,
+ EXTERNAL_ENCODER_CONTROL_DDC_SETUP = 0x14,
};
enum bp_pipe_control_action {
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 8aea50aa9533..92510af1bd65 100644
--- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h
+++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h
@@ -252,6 +252,7 @@ enum {
#define AMDGPU_FAMILY_GC_11_0_0 145
#define AMDGPU_FAMILY_GC_11_0_1 148
#define AMDGPU_FAMILY_GC_11_5_0 150
+#define AMDGPU_FAMILY_GC_11_5_4 154
#define GC_11_0_0_A0 0x1
#define GC_11_0_2_A0 0x10
#define GC_11_0_3_A0 0x20
diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h
index a021d12acd74..d30eb24cf11e 100644
--- a/drivers/gpu/drm/amd/display/include/dal_types.h
+++ b/drivers/gpu/drm/amd/display/include/dal_types.h
@@ -65,6 +65,7 @@ enum dce_version {
DCN_VERSION_3_51,
DCN_VERSION_3_6,
DCN_VERSION_4_01,
+ DCN_VERSION_4_2,
DCN_VERSION_MAX
};
diff --git a/drivers/gpu/drm/amd/display/include/dpcd_defs.h b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
index 1afa10e85eb5..4a8ca0ac1266 100644
--- a/drivers/gpu/drm/amd/display/include/dpcd_defs.h
+++ b/drivers/gpu/drm/amd/display/include/dpcd_defs.h
@@ -64,6 +64,9 @@
#ifndef DP_PR_ERROR_STATUS // can remove this once the define gets into linux drm_dp_helper.h
#define DP_PR_ERROR_STATUS 0x2020 /* DP 2.0 */
#endif /* DP_PR_ERROR_STATUS */
+#ifndef DP_PR_REPLAY_SINK_STATUS // can remove this once the define gets into linux drm_dp_helper.h
+#define DP_PR_REPLAY_SINK_STATUS 0x2022
+#endif /* DP_PR_REPLAY_SINK_STATUS */
#ifndef DP_PR_LINK_CRC_ERROR // can remove this once the define gets into linux drm_dp_helper.h
#define DP_PR_LINK_CRC_ERROR (1 << 0)
#endif /* DP_PR_LINK_CRC_ERROR */
diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
index 2639163b8ba2..1f225d0d6c44 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
+++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
@@ -896,6 +896,7 @@ static void build_de_pq(struct pwl_float_data_ex *de_pq,
uint32_t hw_points_num,
const struct hw_x_point *coordinate_x)
{
+ (void)coordinate_x;
uint32_t i;
struct fixed31_32 output;
struct fixed31_32 *de_pq_table = mod_color_get_table(type_de_pq_table);
@@ -1339,6 +1340,7 @@ static void scale_gamma_dx(struct pwl_float_data *pwl_rgb,
const struct dc_gamma *ramp,
struct dividers dividers)
{
+ (void)dividers;
uint32_t i;
struct fixed31_32 min = dc_fixpt_zero;
struct fixed31_32 max = dc_fixpt_one;
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index 19de72173052..c9150019aab0 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -114,6 +114,7 @@ static unsigned int calc_duration_in_us_from_v_total(
const struct mod_vrr_params *in_vrr,
unsigned int v_total)
{
+ (void)in_vrr;
unsigned int duration_in_us =
(unsigned int)(div64_u64(((unsigned long long)(v_total)
* 10000) * stream->timing.h_total,
@@ -218,6 +219,7 @@ static void update_v_total_for_static_ramp(
const struct dc_stream_state *stream,
struct mod_vrr_params *in_out_vrr)
{
+ (void)core_freesync;
unsigned int v_total = 0;
unsigned int current_duration_in_us =
calc_duration_in_us_from_v_total(
@@ -292,6 +294,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
unsigned int last_render_time_in_us,
struct mod_vrr_params *in_out_vrr)
{
+ (void)core_freesync;
unsigned int inserted_frame_duration_in_us = 0;
unsigned int mid_point_frames_ceil = 0;
unsigned int mid_point_frames_floor = 0;
@@ -447,6 +450,7 @@ static void apply_fixed_refresh(struct core_freesync *core_freesync,
unsigned int last_render_time_in_us,
struct mod_vrr_params *in_out_vrr)
{
+ (void)core_freesync;
bool update = false;
unsigned int max_render_time_in_us = in_out_vrr->max_duration_in_us;
@@ -545,6 +549,7 @@ static bool vrr_settings_require_update(struct core_freesync *core_freesync,
unsigned int max_refresh_in_uhz,
struct mod_vrr_params *in_vrr)
{
+ (void)core_freesync;
if (in_vrr->state != in_config->state) {
return true;
} else if (in_vrr->state == VRR_STATE_ACTIVE_FIXED &&
@@ -946,6 +951,7 @@ void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync,
struct dc_info_packet *infopacket,
bool pack_sdp_v1_3)
{
+ (void)mod_freesync;
/* SPD info packet for FreeSync
* VTEM info packet for HdmiVRR
* Check if Freesync is supported. Return if false. If true,
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
index 26a351a184f3..d07387a961dd 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h
@@ -501,6 +501,7 @@ static inline void callback_in_ms(uint16_t time, struct mod_hdcp_output *output)
static inline void set_watchdog_in_ms(struct mod_hdcp *hdcp, uint16_t time,
struct mod_hdcp_output *output)
{
+ (void)hdcp;
output->watchdog_timer_needed = 1;
output->watchdog_timer_delay = time;
}