From 5bdf199db700706cdbd61a0bb8204a900ce9b5cb Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Fri, 19 Apr 2024 13:28:17 -0400 Subject: drm/amd/display: Fix SPL related enum definition used in DCN401 Remove a duplicate definition of an SPL related enum transform.h Since its used in SPL, it has been moved to its own header. Signed-off-by: Aurabindo Pillai Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 3c33c3bcbe2c..97c78cadb603 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -46,6 +46,8 @@ #include "dmub/inc/dmub_cmd.h" +#include "spl/dc_spl_types.h" + struct abm_save_restore; /* forward declaration */ -- cgit From 00c391102abc13763e2bfc90e05503109b19f074 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Wed, 20 Mar 2024 13:56:16 -0400 Subject: drm/amd/display: Add misc DC changes for DCN401 Add miscellaneous changes to enable DCN401 init Signed-off-by: Aurabindo Pillai Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 33 ++- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 12 +- drivers/gpu/drm/amd/display/dc/Makefile | 9 + drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 109 ++++++++- .../amd/display/dc/bios/command_table_helper2.c | 1 + drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile | 9 + drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 16 ++ drivers/gpu/drm/amd/display/dc/core/dc.c | 261 ++++++++++++++++++++- .../gpu/drm/amd/display/dc/core/dc_hw_sequencer.c | 43 ++++ drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 44 +++- drivers/gpu/drm/amd/display/dc/core/dc_state.c | 16 ++ drivers/gpu/drm/amd/display/dc/dc.h | 45 +++- drivers/gpu/drm/amd/display/dc/dc_bios_types.h | 1 + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 176 ++++++++++++++ drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 18 +- drivers/gpu/drm/amd/display/dc/dc_helper.c | 3 +- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 50 +++- drivers/gpu/drm/amd/display/dc/dc_state_priv.h | 4 + drivers/gpu/drm/amd/display/dc/dc_types.h | 77 ++++++ .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 117 +++++++++ .../gpu/drm/amd/display/dc/dce/dce_clock_source.h | 8 + drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h | 4 + .../amd/display/dc/dcn10/dcn10_stream_encoder.h | 4 +- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h | 4 + .../gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c | 2 +- .../gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h | 2 + drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c | 3 + drivers/gpu/drm/amd/display/dc/dml/Makefile | 4 + .../display/dc/dml/dcn314/display_mode_vba_314.c | 3 - .../drm/amd/display/dc/dml/display_mode_structs.h | 1 + drivers/gpu/drm/amd/display/dc/dml2/Makefile | 80 +++++++ .../display/dc/dml2/display_mode_core_structs.h | 1 + .../amd/display/dc/dml2/dml2_dc_resource_mgmt.c | 74 +++++- .../drm/amd/display/dc/dml2/dml2_internal_types.h | 20 ++ .../amd/display/dc/dml2/dml2_translation_helper.c | 126 +++++++++- drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c | 30 +++ drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h | 14 ++ drivers/gpu/drm/amd/display/dc/dpp/Makefile | 8 +- .../gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c | 56 +++++ .../gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.h | 9 +- .../gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.h | 4 +- .../gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.c | 73 ++++++ .../gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.h | 8 + drivers/gpu/drm/amd/display/dc/dsc/Makefile | 8 +- drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 102 +------- drivers/gpu/drm/amd/display/dc/gpio/Makefile | 10 + drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c | 4 + drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c | 4 + drivers/gpu/drm/amd/display/dc/hwss/Makefile | 5 + .../drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 7 +- .../drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 18 +- .../gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c | 2 + drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h | 22 ++ .../drm/amd/display/dc/hwss/hw_sequencer_private.h | 4 + drivers/gpu/drm/amd/display/dc/inc/core_types.h | 21 +- drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h | 6 +- .../drm/amd/display/dc/inc/hw/clk_mgr_internal.h | 44 ++-- drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h | 15 ++ drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 4 + drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h | 56 ++++- drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h | 9 +- drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 36 ++- drivers/gpu/drm/amd/display/dc/inc/hw/transform.h | 12 + drivers/gpu/drm/amd/display/dc/inc/resource.h | 8 +- drivers/gpu/drm/amd/display/dc/irq/Makefile | 9 + drivers/gpu/drm/amd/display/dc/optc/Makefile | 6 + .../gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h | 3 - drivers/gpu/drm/amd/display/dc/resource/Makefile | 8 + .../amd/display/dc/resource/dcn32/dcn32_resource.c | 1 + drivers/gpu/drm/amd/display/include/dal_asic_id.h | 11 + drivers/gpu/drm/amd/display/include/dal_types.h | 1 + 72 files changed, 1838 insertions(+), 182 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') 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 73cb88121382..3bd3a218b604 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -151,6 +151,9 @@ MODULE_FIRMWARE(FIRMWARE_DCN_35_DMUB); #define FIRMWARE_DCN_351_DMUB "amdgpu/dcn_3_5_1_dmcub.bin" MODULE_FIRMWARE(FIRMWARE_DCN_351_DMUB); +#define FIRMWARE_DCN_401_DMUB "amdgpu/dcn_4_0_1_dmcub.bin" +MODULE_FIRMWARE(FIRMWARE_DCN_401_DMUB); + /* Number of bytes in PSP header for firmware. */ #define PSP_HEADER_BYTES 0x100 @@ -1223,6 +1226,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev) case IP_VERSION(3, 1, 4): case IP_VERSION(3, 5, 0): case IP_VERSION(3, 5, 1): + case IP_VERSION(4, 0, 1): hw_params.dpia_supported = true; hw_params.disable_dpia = adev->dm.dc->debug.dpia_debug.bits.disable_dpia; break; @@ -1781,8 +1785,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) if (amdgpu_dc_debug_mask & DC_FORCE_SUBVP_MCLK_SWITCH) adev->dm.dc->debug.force_subvp_mclk_switch = true; - if (amdgpu_dc_debug_mask & DC_ENABLE_DML2) + if (amdgpu_dc_debug_mask & DC_ENABLE_DML2) { adev->dm.dc->debug.using_dml2 = true; + adev->dm.dc->debug.using_dml21 = true; + } adev->dm.dc->debug.visual_confirm = amdgpu_dc_visual_confirm; @@ -2059,6 +2065,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev) case IP_VERSION(3, 2, 1): case IP_VERSION(3, 5, 0): case IP_VERSION(3, 5, 1): + case IP_VERSION(4, 0, 1): return 0; default: break; @@ -2182,6 +2189,10 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) case IP_VERSION(3, 5, 1): dmub_asic = DMUB_ASIC_DCN35; break; + case IP_VERSION(4, 0, 1): + dmub_asic = DMUB_ASIC_DCN401; + break; + default: /* ASIC doesn't support DMUB. */ return 0; @@ -4523,6 +4534,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case IP_VERSION(2, 1, 0): case IP_VERSION(3, 5, 0): case IP_VERSION(3, 5, 1): + case IP_VERSION(4, 0, 1): if (register_outbox_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); goto fail; @@ -4545,6 +4557,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case IP_VERSION(3, 2, 1): case IP_VERSION(3, 5, 0): case IP_VERSION(3, 5, 1): + case IP_VERSION(4, 0, 1): psr_feature_enabled = true; break; default: @@ -4716,6 +4729,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) case IP_VERSION(3, 2, 1): case IP_VERSION(3, 5, 0): case IP_VERSION(3, 5, 1): + case IP_VERSION(4, 0, 1): if (dcn10_register_irq_handlers(dm->adev)) { DRM_ERROR("DM: Failed to initialize IRQ\n"); goto fail; @@ -4852,6 +4866,9 @@ static int dm_init_microcode(struct amdgpu_device *adev) case IP_VERSION(3, 5, 1): fw_name_dmub = FIRMWARE_DCN_351_DMUB; break; + case IP_VERSION(4, 0, 1): + fw_name_dmub = FIRMWARE_DCN_401_DMUB; + break; default: /* ASIC doesn't support DMUB. */ return 0; @@ -4976,6 +4993,7 @@ static int dm_early_init(void *handle) case IP_VERSION(3, 2, 1): case IP_VERSION(3, 5, 0): case IP_VERSION(3, 5, 1): + case IP_VERSION(4, 0, 1): adev->mode_info.num_crtc = 4; adev->mode_info.num_hpd = 4; adev->mode_info.num_dig = 4; @@ -6023,6 +6041,7 @@ static bool is_freesync_video_mode(const struct drm_display_mode *mode, return true; } +#if defined(CONFIG_DRM_AMD_DC_FP) static void update_dsc_caps(struct amdgpu_dm_connector *aconnector, struct dc_sink *sink, struct dc_stream_state *stream, struct dsc_dec_dpcd_caps *dsc_caps) @@ -6041,7 +6060,6 @@ static void update_dsc_caps(struct amdgpu_dm_connector *aconnector, } } - static void apply_dsc_policy_for_edp(struct amdgpu_dm_connector *aconnector, struct dc_sink *sink, struct dc_stream_state *stream, struct dsc_dec_dpcd_caps *dsc_caps, @@ -6105,7 +6123,6 @@ static void apply_dsc_policy_for_edp(struct amdgpu_dm_connector *aconnector, } } - static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector, struct dc_sink *sink, struct dc_stream_state *stream, struct dsc_dec_dpcd_caps *dsc_caps) @@ -6183,6 +6200,7 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector, if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_bits_per_pixel) stream->timing.dsc_cfg.bits_per_pixel = aconnector->dsc_settings.dsc_bits_per_pixel; } +#endif static struct dc_stream_state * create_stream_for_sink(struct drm_connector *connector, @@ -6204,8 +6222,9 @@ create_stream_for_sink(struct drm_connector *connector, int mode_refresh; int preferred_refresh = 0; enum color_transfer_func tf = TRANSFER_FUNC_UNKNOWN; +#if defined(CONFIG_DRM_AMD_DC_FP) struct dsc_dec_dpcd_caps dsc_caps; - +#endif struct dc_link *link = NULL; struct dc_sink *sink = NULL; @@ -6321,10 +6340,12 @@ create_stream_for_sink(struct drm_connector *connector, stream->timing = *aconnector->timing_requested; } +#if defined(CONFIG_DRM_AMD_DC_FP) /* SST DSC determination policy */ update_dsc_caps(aconnector, sink, stream, &dsc_caps); if (aconnector->dsc_settings.dsc_force_enable != DSC_CLK_FORCE_DISABLE && dsc_caps.is_dsc_supported) apply_dsc_policy_for_stream(aconnector, sink, stream, &dsc_caps); +#endif update_stream_scaling_settings(&mode, dm_state, stream); @@ -10799,11 +10820,13 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } } +#if defined(CONFIG_DRM_AMD_DC_FP) if (dc_resource_is_dsc_encoding_supported(dc)) { ret = pre_validate_dsc(state, &dm_state, vars); if (ret != 0) goto fail; } +#endif /* Run this here since we want to validate the streams we created */ ret = drm_atomic_helper_check_planes(dev, state); @@ -10915,6 +10938,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; } +#if defined(CONFIG_DRM_AMD_DC_FP) if (dc_resource_is_dsc_encoding_supported(dc)) { ret = compute_mst_dsc_configs_for_state(state, dm_state->context, vars); if (ret) { @@ -10923,6 +10947,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, goto fail; } } +#endif ret = dm_update_mst_vcpi_slots_for_dsc(state, dm_state->context, vars); if (ret) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 0b03e659fdf3..9469cc831597 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -210,6 +210,7 @@ bool needs_dsc_aux_workaround(struct dc_link *link) return false; } +#if defined(CONFIG_DRM_AMD_DC_FP) static bool is_synaptics_cascaded_panamera(struct dc_link *link, struct drm_dp_mst_port *port) { u8 branch_vendor_data[4] = { 0 }; // Vendor data 0x50C ~ 0x50F @@ -269,6 +270,7 @@ static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnecto return true; } +#endif static bool retrieve_downstream_port_device(struct amdgpu_dm_connector *aconnector) { @@ -402,9 +404,11 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) amdgpu_dm_update_freesync_caps( connector, aconnector->edid); +#if defined(CONFIG_DRM_AMD_DC_FP) if (!validate_dsc_caps_on_connector(aconnector)) memset(&aconnector->dc_sink->dsc_caps, 0, sizeof(aconnector->dc_sink->dsc_caps)); +#endif if (!retrieve_downstream_port_device(aconnector)) memset(&aconnector->mst_downstream_port_present, @@ -791,6 +795,7 @@ struct dsc_mst_fairness_params { struct amdgpu_dm_connector *aconnector; }; +#if defined(CONFIG_DRM_AMD_DC_FP) static int kbps_to_peak_pbn(int kbps) { u64 peak_kbps = kbps; @@ -1581,13 +1586,16 @@ static bool is_dsc_common_config_possible(struct dc_stream_state *stream, return bw_range->max_target_bpp_x16 && bw_range->min_target_bpp_x16; } +#endif enum dc_status dm_dp_mst_is_port_support_mode( struct amdgpu_dm_connector *aconnector, struct dc_stream_state *stream) { - int pbn, branch_max_throughput_mps = 0; + int branch_max_throughput_mps = 0; +#if defined(CONFIG_DRM_AMD_DC_FP) struct dc_link_settings cur_link_settings; + int pbn; unsigned int end_to_end_bw_in_kbps = 0; unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0; struct dc_dsc_bw_range bw_range = {0}; @@ -1665,7 +1673,6 @@ enum dc_status dm_dp_mst_is_port_support_mode( return DC_FAIL_BANDWIDTH_VALIDATE; } } - /* check is mst dsc output bandwidth branch_overall_throughput_0_mps */ switch (stream->timing.pixel_encoding) { case PIXEL_ENCODING_RGB: @@ -1681,6 +1688,7 @@ enum dc_status dm_dp_mst_is_port_support_mode( default: break; } +#endif if (branch_max_throughput_mps != 0 && ((stream->timing.pix_clk_100hz / 10) > branch_max_throughput_mps * 1000)) diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 4e9fb1742877..8d963befc756 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -39,6 +39,7 @@ DC_LIBS += dcn314 DC_LIBS += dcn32 DC_LIBS += dcn321 DC_LIBS += dcn35 +DC_LIBS += dcn401 DC_LIBS += dml DC_LIBS += dml2 endif @@ -55,6 +56,11 @@ endif DC_LIBS += hdcp +ifdef CONFIG_DRM_AMD_DC_FP +DC_LIBS += spl +DC_SPL_TRANS += dc_spl_translate.o +endif + AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LIBS))) include $(AMD_DC) @@ -68,6 +74,8 @@ AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE)) AMD_DM_REG_UPDATE = $(addprefix $(AMDDALPATH)/dc/,dc_helper.o) +AMD_DC_SPL_TRANS = $(addprefix $(AMDDALPATH)/dc/,$(DC_SPL_TRANS)) + AMD_DISPLAY_FILES += $(AMD_DISPLAY_CORE) AMD_DISPLAY_FILES += $(AMD_DM_REG_UPDATE) @@ -77,3 +85,4 @@ AMD_DISPLAY_DMUB = $(addprefix $(AMDDALPATH)/dc/,$(DC_DMUB)) AMD_DISPLAY_EDID = $(addprefix $(AMDDALPATH)/dc/,$(DC_EDID)) AMD_DISPLAY_FILES += $(AMD_DISPLAY_DMUB) $(AMD_DISPLAY_EDID) +AMD_DISPLAY_FILES += $(AMD_DC_SPL_TRANS) 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 517c976dbc19..bafd3801de34 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -75,6 +75,10 @@ static enum bp_result get_firmware_info_v3_4( struct bios_parser *bp, struct dc_firmware_info *info); +static enum bp_result get_firmware_info_v3_5( + struct bios_parser *bp, + struct dc_firmware_info *info); + static struct atom_hpd_int_record *get_hpd_record(struct bios_parser *bp, struct atom_display_object_path_v2 *object); @@ -1754,6 +1758,9 @@ static enum bp_result bios_parser_get_firmware_info( case 4: result = get_firmware_info_v3_4(bp, info); break; + case 5: + result = get_firmware_info_v3_5(bp, info); + break; default: break; } @@ -2044,6 +2051,63 @@ static enum bp_result get_firmware_info_v3_4( return BP_RESULT_OK; } +static enum bp_result get_firmware_info_v3_5( + struct bios_parser *bp, + struct dc_firmware_info *info) +{ + struct atom_firmware_info_v3_5 *firmware_info; + struct atom_common_table_header *header; + struct atom_data_revision revision; + struct atom_display_controller_info_v4_5 *dce_info_v4_5 = NULL; + + if (!info) + return BP_RESULT_BADINPUT; + + firmware_info = GET_IMAGE(struct atom_firmware_info_v3_5, + DATA_TABLES(firmwareinfo)); + + if (!firmware_info) + return BP_RESULT_BADBIOSTABLE; + + memset(info, 0, sizeof(*info)); + + if (firmware_info->board_i2c_feature_id == 0x2) { + info->oem_i2c_present = true; + info->oem_i2c_obj_id = firmware_info->board_i2c_feature_gpio_id; + } else { + info->oem_i2c_present = false; + } + + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(dce_info)); + + get_atom_data_table_revision(header, &revision); + + switch (revision.major) { + case 4: + switch (revision.minor) { + case 5: + dce_info_v4_5 = GET_IMAGE(struct atom_display_controller_info_v4_5, + DATA_TABLES(dce_info)); + + if (!dce_info_v4_5) + return BP_RESULT_BADBIOSTABLE; + + /* 100MHz expected */ + info->pll_info.crystal_frequency = dce_info_v4_5->dce_refclk_10khz * 10; + break; + default: + break; + } + break; + default: + break; + } + + + return BP_RESULT_OK; +} + static enum bp_result bios_parser_get_encoder_cap_info( struct dc_bios *dcb, struct graphics_object_id object_id, @@ -2398,6 +2462,25 @@ static enum bp_result get_vram_info_v30( return result; } +static enum bp_result get_vram_info_from_umc_info_v40( + struct bios_parser *bp, + struct dc_vram_info *info) +{ + struct atom_umc_info_v4_0 *info_v40; + enum bp_result result = BP_RESULT_OK; + + info_v40 = GET_IMAGE(struct atom_umc_info_v4_0, + DATA_TABLES(umc_info)); + + if (info_v40 == NULL) + return BP_RESULT_BADBIOSTABLE; + + info->num_chans = info_v40->channel_num; + info->dram_channel_width_bytes = (1 << info_v40->channel_width) / 8; + + return result; +} + /* * get_integrated_info_v11 * @@ -3039,7 +3122,29 @@ static enum bp_result bios_parser_get_vram_info( struct atom_common_table_header *header; struct atom_data_revision revision; - if (info && DATA_TABLES(vram_info)) { + // vram info moved to umc_info for DCN4x + if (info && DATA_TABLES(umc_info)) { + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(umc_info)); + + get_atom_data_table_revision(header, &revision); + + switch (revision.major) { + case 4: + switch (revision.minor) { + case 0: + result = get_vram_info_from_umc_info_v40(bp, info); + break; + default: + break; + } + break; + default: + break; + } + } + + if (result != BP_RESULT_OK && info && DATA_TABLES(vram_info)) { header = GET_IMAGE(struct atom_common_table_header, DATA_TABLES(vram_info)); @@ -3662,7 +3767,7 @@ static bool bios_parser2_construct( bp->base.integrated_info = bios_parser_create_integrated_info(&bp->base); bp->base.fw_info_valid = bios_parser_get_firmware_info(&bp->base, &bp->base.fw_info) == BP_RESULT_OK; bios_parser_get_vram_info(&bp->base, &bp->base.vram_info); - + bios_parser_get_soc_bb_info(&bp->base, &bp->base.bb_info); return true; } 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 117fc6d4c1de..73458e295103 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 @@ -82,6 +82,7 @@ bool dal_bios_parser_init_cmd_tbl_helper2( case DCN_VERSION_3_21: case DCN_VERSION_3_5: case DCN_VERSION_3_51: + case DCN_VERSION_4_01: *h = dal_cmd_tbl_helper_dce112_get_table2(); return true; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile index 1c443e549afa..dfaa200ecf1a 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile @@ -180,4 +180,13 @@ CLK_MGR_DCN35 = dcn35_smu.o dcn35_clk_mgr.o AMD_DAL_CLK_MGR_DCN35 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn35/,$(CLK_MGR_DCN35)) AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN35) + +############################################################################### +# DCN401 +############################################################################### +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) 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 a2b4ff2cff16..5f67d159e1e2 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 @@ -48,6 +48,7 @@ #include "dcn316/dcn316_clk_mgr.h" #include "dcn32/dcn32_clk_mgr.h" #include "dcn35/dcn35_clk_mgr.h" +#include "dcn401/dcn401_clk_mgr.h" int clk_mgr_helper_get_active_display_cnt( struct dc *dc, @@ -365,6 +366,18 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p } break; + case AMDGPU_FAMILY_GC_12_0_0: { + struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); + + if (clk_mgr == NULL) { + BREAK_TO_DEBUGGER(); + return NULL; + } + + dcn401_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); + return &clk_mgr->base; + } + break; #endif /* CONFIG_DRM_AMD_DC_FP */ default: ASSERT(0); /* Unknown Asic */ @@ -419,6 +432,9 @@ void dc_destroy_clk_mgr(struct clk_mgr *clk_mgr_base) case AMDGPU_FAMILY_GC_11_5_0: dcn35_clk_mgr_destroy(clk_mgr); break; + case AMDGPU_FAMILY_GC_12_0_0: + dcn401_clk_mgr_destroy(clk_mgr); + break; default: break; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index eb2aa90b370b..3d817d030837 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -80,7 +80,9 @@ #include "hw_sequencer_private.h" +#if defined(CONFIG_DRM_AMD_DC_FP) #include "dml2/dml2_internal_types.h" +#endif #include "dce/dmub_outbox.h" @@ -1162,6 +1164,8 @@ static void dc_update_visual_confirm_color(struct dc *dc, struct dc_state *conte get_subvp_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); else if (dc->debug.visual_confirm == VISUAL_CONFIRM_MCLK_SWITCH) get_mclk_switch_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color)); + else if (dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS2) + get_fams2_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color)); } } } @@ -1457,8 +1461,6 @@ struct dc *dc_create(const struct dc_init_data *init_params) DC_LOG_DC("Display Core initialized\n"); - - return dc; destruct_dc: @@ -1971,6 +1973,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c */ if (dc->hwss.subvp_pipe_control_lock) dc->hwss.subvp_pipe_control_lock(dc, context, true, true, NULL, subvp_prev_use); + if (dc->hwss.fams2_global_control_lock) + dc->hwss.fams2_global_control_lock(dc, context, true); if (dc->hwss.update_dsc_pg) dc->hwss.update_dsc_pg(dc, context, false); @@ -2029,6 +2033,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c dc->hwss.commit_subvp_config(dc, context); if (dc->hwss.subvp_pipe_control_lock) dc->hwss.subvp_pipe_control_lock(dc, context, false, true, NULL, subvp_prev_use); + if (dc->hwss.fams2_global_control_lock) + dc->hwss.fams2_global_control_lock(dc, context, false); for (i = 0; i < context->stream_count; i++) { const struct dc_link *link = context->streams[i]->link; @@ -2632,6 +2638,16 @@ static enum surface_update_type det_surface_update(const struct dc *dc, elevate_update_type(&overall_type, UPDATE_TYPE_MED); } + 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)) + update_flags->bits.mcm_transfer_function_enable_change = 1; + if (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; + } if (update_flags->bits.in_transfer_func_change) { type = UPDATE_TYPE_MED; elevate_update_type(&overall_type, type); @@ -2641,6 +2657,10 @@ static enum surface_update_type det_surface_update(const struct dc *dc, type = UPDATE_TYPE_FULL; elevate_update_type(&overall_type, type); } + if (update_flags->bits.mcm_transfer_function_enable_change) { + type = UPDATE_TYPE_FULL; + elevate_update_type(&overall_type, type); + } if (dc->debug.enable_legacy_fast_update && (update_flags->bits.gamma_change || @@ -2906,6 +2926,14 @@ static void copy_surface_update_to_plane( if (srf_update->gamut_remap_matrix) surface->gamut_remap_matrix = *srf_update->gamut_remap_matrix; + 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->cursor_csc_color_matrix) + surface->cursor_csc_color_matrix = + *srf_update->cursor_csc_color_matrix; } static void copy_stream_update_to_stream(struct dc *dc, @@ -3521,6 +3549,15 @@ static void build_dmub_update_dirty_rect( } } +static bool check_address_only_update(union surface_update_flags update_flags) +{ + union surface_update_flags addr_only_update_flags; + addr_only_update_flags.raw = 0; + addr_only_update_flags.bits.addr_update = 1; + + return update_flags.bits.addr_update && + !(update_flags.raw & ~addr_only_update_flags.raw); +} /** * build_dmub_cmd_list() - Build an array of DMCUB commands to be sent to DMCUB @@ -3552,6 +3589,54 @@ static void build_dmub_cmd_list(struct dc *dc, build_dmub_update_dirty_rect(dc, surface_count, stream, srf_updates, context, dc_dmub_cmd, dmub_cmd_count); } +static void commit_plane_for_stream_offload_fams2_flip(struct dc *dc, + struct dc_surface_update *srf_updates, + int surface_count, + struct dc_stream_state *stream, + struct dc_state *context) +{ + int i, j; + + /* update dirty rect for PSR */ + dc_dmub_update_dirty_rect(dc, surface_count, stream, + srf_updates, context); + + /* Perform requested Updates */ + for (i = 0; i < surface_count; i++) { + struct dc_plane_state *plane_state = srf_updates[i].surface; + + /* set offload flag so driver does not program address */ + plane_state->address.offload_flip = true; + + for (j = 0; j < dc->res_pool->pipe_count; j++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; + + if (!should_update_pipe_for_stream(context, pipe_ctx, stream)) + continue; + + if (!should_update_pipe_for_plane(context, pipe_ctx, plane_state)) + continue; + + /* update pipe context for plane */ + if (pipe_ctx->plane_state->update_flags.bits.addr_update) + dc->hwss.update_plane_addr(dc, pipe_ctx); + } + } + + /* Send commands to DMCUB */ + dc_dmub_srv_fams2_passthrough_flip(dc, + context, + stream, + srf_updates, + surface_count); + + /* reset offload flip flag */ + for (i = 0; i < surface_count; i++) { + struct dc_plane_state *plane_state = srf_updates[i].surface; + plane_state->address.offload_flip = false; + } +} + static void commit_planes_for_stream_fast(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, @@ -3563,6 +3648,23 @@ static void commit_planes_for_stream_fast(struct dc *dc, int i, j; struct pipe_ctx *top_pipe_to_program = NULL; struct dc_stream_status *stream_status = NULL; + bool should_offload_fams2_flip = false; + + if (dc->debug.fams2_config.bits.enable && + dc->debug.fams2_config.bits.enable_offload_flip && + dc_state_is_fams2_in_use(dc, context)) { + /* if not offloading to HWFQ, offload to FAMS2 if needed */ + should_offload_fams2_flip = true; + for (i = 0; i < surface_count; i++) { + if (srf_updates[i].surface && + srf_updates[i].surface->update_flags.raw && + !check_address_only_update(srf_updates[i].surface->update_flags)) { + /* more than address update, need to acquire FAMS2 lock */ + should_offload_fams2_flip = false; + break; + } + } + } dc_exit_ips_for_hw_access(dc); @@ -3598,7 +3700,7 @@ static void commit_planes_for_stream_fast(struct dc *dc, continue; pipe_ctx->plane_state->triplebuffer_flips = false; if (update_type == UPDATE_TYPE_FAST && - dc->hwss.program_triplebuffer && + dc->hwss.program_triplebuffer != NULL && !pipe_ctx->plane_state->flip_immediate && dc->debug.enable_tri_buf) { /*triple buffer for VUpdate only*/ pipe_ctx->plane_state->triplebuffer_flips = true; @@ -3608,6 +3710,33 @@ static void commit_planes_for_stream_fast(struct dc *dc, stream_status = dc_state_get_stream_status(context, stream); + if (should_offload_fams2_flip) { + commit_plane_for_stream_offload_fams2_flip(dc, + srf_updates, + surface_count, + stream, + context); + } else { + build_dmub_cmd_list(dc, + srf_updates, + surface_count, + stream, + context, + context->dc_dmub_cmd, + &(context->dmub_cmd_count)); + hwss_build_fast_sequence(dc, + context->dc_dmub_cmd, + context->dmub_cmd_count, + context->block_sequence, + &(context->block_sequence_steps), + top_pipe_to_program, + stream_status, + context); + hwss_execute_sequence(dc, + context->block_sequence, + context->block_sequence_steps); + } + build_dmub_cmd_list(dc, srf_updates, surface_count, @@ -3776,12 +3905,19 @@ static void commit_planes_for_stream(struct dc *dc, if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { if (dc->hwss.subvp_pipe_control_lock) - dc->hwss.subvp_pipe_control_lock(dc, context, true, should_lock_all_pipes, NULL, subvp_prev_use); - dc->hwss.interdependent_update_lock(dc, context, true); + dc->hwss.subvp_pipe_control_lock(dc, context, true, should_lock_all_pipes, NULL, subvp_prev_use); + + if (dc->hwss.fams2_global_control_lock) + dc->hwss.fams2_global_control_lock(dc, context, true); + dc->hwss.interdependent_update_lock(dc, context, true); } else { if (dc->hwss.subvp_pipe_control_lock) dc->hwss.subvp_pipe_control_lock(dc, context, true, should_lock_all_pipes, top_pipe_to_program, subvp_prev_use); + + if (dc->hwss.fams2_global_control_lock) + dc->hwss.fams2_global_control_lock(dc, context, true); + /* Lock the top pipe while updating plane addrs, since freesync requires * plane addr update event triggers to be synchronized. * top_pipe_to_program is expected to never be NULL @@ -3822,6 +3958,10 @@ static void commit_planes_for_stream(struct dc *dc, if (dc->hwss.subvp_pipe_control_lock) dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use); + + if (dc->hwss.fams2_global_control_lock) + dc->hwss.fams2_global_control_lock(dc, context, false); + return; } @@ -4025,9 +4165,13 @@ static void commit_planes_for_stream(struct dc *dc, if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { if (dc->hwss.subvp_pipe_control_lock) dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use); + if (dc->hwss.fams2_global_control_lock) + dc->hwss.fams2_global_control_lock(dc, context, false); } else { if (dc->hwss.subvp_pipe_control_lock) dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, top_pipe_to_program, subvp_prev_use); + if (dc->hwss.fams2_global_control_lock) + dc->hwss.fams2_global_control_lock(dc, context, false); } // Fire manual trigger only when bottom plane is flipped @@ -4539,6 +4683,7 @@ static void populate_fast_updates(struct dc_fast_update *fast_update, fast_update[i].gamut_remap_matrix = srf_updates[i].gamut_remap_matrix; 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; } } @@ -4555,6 +4700,7 @@ static bool fast_updates_exist(struct dc_fast_update *fast_update, int surface_c fast_update[i].gamma || fast_update[i].gamut_remap_matrix || fast_update[i].input_csc_color_matrix || + fast_update[i].cursor_csc_color_matrix || fast_update[i].coeff_reduction_factor) return true; } @@ -4585,6 +4731,9 @@ static bool full_update_required(struct dc *dc, 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)) || !is_surface_in_context(context, srf_updates[i].surface))) return true; } @@ -4969,7 +5118,7 @@ bool dc_update_planes_and_stream(struct dc *dc, * specially handle compatibility problems with transitions among those * features as they are now transparent to the new sequence. */ - if (dc->ctx->dce_version > DCN_VERSION_3_51) + if (dc->ctx->dce_version > DCN_VERSION_4_01) return update_planes_and_stream_v3(dc, srf_updates, surface_count, stream, stream_update); return update_planes_and_stream_v2(dc, srf_updates, @@ -4989,7 +5138,7 @@ void dc_commit_updates_for_stream(struct dc *dc, * we get more confident about this change we'll need to enable * the new sequence for all ASICs. */ - if (dc->ctx->dce_version > DCN_VERSION_3_51) { + if (dc->ctx->dce_version > DCN_VERSION_4_01) { update_planes_and_stream_v3(dc, srf_updates, surface_count, stream, stream_update); return; @@ -5829,3 +5978,101 @@ struct dc_power_profile dc_get_power_profile_for_dc_state(const struct dc_state return profile; } +/* Need to account for padding due to pixel-to-symbol packing + * for uncompressed 128b/132b streams. + */ +static uint32_t apply_128b_132b_stream_overhead( + const struct dc_crtc_timing *timing, const uint32_t kbps) +{ + uint32_t total_kbps = kbps; +#if defined(CONFIG_DRM_AMD_DC_FP) + if (dc_get_disable_128b_132b_stream_overhead()) + return kbps; +#endif + + if (!timing->flags.DSC) { + struct fixed31_32 bpp; + struct fixed31_32 overhead_factor; + + bpp = dc_fixpt_from_int(kbps); + bpp = dc_fixpt_div_int(bpp, timing->pix_clk_100hz / 10); + + /* Symbols_per_HActive = HActive * bpp / (4 lanes * 32-bit symbol size) + * Overhead_factor = ceil(Symbols_per_HActive) / Symbols_per_HActive + */ + overhead_factor = dc_fixpt_from_int(timing->h_addressable); + overhead_factor = dc_fixpt_mul(overhead_factor, bpp); + overhead_factor = dc_fixpt_div_int(overhead_factor, 128); + overhead_factor = dc_fixpt_div( + dc_fixpt_from_int(dc_fixpt_ceil(overhead_factor)), + overhead_factor); + + total_kbps = dc_fixpt_ceil( + dc_fixpt_mul_int(overhead_factor, total_kbps)); + } + + return total_kbps; +} + +uint32_t dc_bandwidth_in_kbps_from_timing( + const struct dc_crtc_timing *timing, + const enum dc_link_encoding_format link_encoding) +{ + uint32_t bits_per_channel = 0; + uint32_t kbps; + +#if defined(CONFIG_DRM_AMD_DC_FP) + if (timing->flags.DSC) + return dc_dsc_stream_bandwidth_in_kbps(timing, + timing->dsc_cfg.bits_per_pixel, + timing->dsc_cfg.num_slices_h, + timing->dsc_cfg.is_dp); +#endif + + switch (timing->display_color_depth) { + case COLOR_DEPTH_666: + bits_per_channel = 6; + break; + case COLOR_DEPTH_888: + bits_per_channel = 8; + break; + case COLOR_DEPTH_101010: + bits_per_channel = 10; + break; + case COLOR_DEPTH_121212: + bits_per_channel = 12; + break; + case COLOR_DEPTH_141414: + bits_per_channel = 14; + break; + case COLOR_DEPTH_161616: + bits_per_channel = 16; + break; + default: + ASSERT(bits_per_channel != 0); + bits_per_channel = 8; + break; + } + + kbps = timing->pix_clk_100hz / 10; + kbps *= bits_per_channel; + + if (timing->flags.Y_ONLY != 1) { + /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/ + kbps *= 3; + if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) + kbps /= 2; + else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) + kbps = kbps * 2 / 3; + } + + if (link_encoding == DC_LINK_ENCODING_DP_128b_132b) + kbps = apply_128b_132b_stream_overhead(timing, kbps); + + if (link_encoding == DC_LINK_ENCODING_HDMI_FRL && + timing->vic == 0 && timing->hdmi_vic == 0 && + timing->frl_uncompressed_video_bandwidth_in_kbps != 0) + kbps = timing->frl_uncompressed_video_bandwidth_in_kbps; + + return kbps; +} 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 5c1d3017aefd..33318a112282 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 @@ -554,6 +554,26 @@ void set_p_state_switch_method( } } +void get_fams2_visual_confirm_color( + struct dc *dc, + struct dc_state *context, + struct pipe_ctx *pipe_ctx, + struct tg_color *color) +{ + uint32_t color_value = MAX_TG_COLOR_VALUE; + + if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !context || !dc->debug.fams2_config.bits.enable) + return; + + /* driver only handles visual confirm when FAMS2 is disabled */ + if (!dc_state_is_fams2_in_use(dc, context)) { + /* when FAMS2 is disabled, all pipes are grey */ + color->color_g_y = color_value / 2; + color->color_b_cb = color_value / 2; + color->color_r_cr = color_value / 2; + } +} + void hwss_build_fast_sequence(struct dc *dc, struct dc_dmub_cmd *dc_dmub_cmd, unsigned int dmub_cmd_count, @@ -583,6 +603,13 @@ void hwss_build_fast_sequence(struct dc *dc, block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST; (*num_steps)++; } + if (dc->hwss.fams2_global_control_lock_fast) { + block_sequence[*num_steps].params.fams2_global_control_lock_fast_params.dc = dc; + block_sequence[*num_steps].params.fams2_global_control_lock_fast_params.lock = true; + block_sequence[*num_steps].params.fams2_global_control_lock_fast_params.is_required = dc_state_is_fams2_in_use(dc, context); + block_sequence[*num_steps].func = DMUB_FAMS2_GLOBAL_CONTROL_LOCK_FAST; + (*num_steps)++; + } if (dc->hwss.pipe_control_lock) { block_sequence[*num_steps].params.pipe_control_lock_params.dc = dc; block_sequence[*num_steps].params.pipe_control_lock_params.lock = true; @@ -706,6 +733,13 @@ void hwss_build_fast_sequence(struct dc *dc, block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST; (*num_steps)++; } + if (dc->hwss.fams2_global_control_lock_fast) { + block_sequence[*num_steps].params.fams2_global_control_lock_fast_params.dc = dc; + block_sequence[*num_steps].params.fams2_global_control_lock_fast_params.lock = false; + block_sequence[*num_steps].params.fams2_global_control_lock_fast_params.is_required = dc_state_is_fams2_in_use(dc, context); + block_sequence[*num_steps].func = DMUB_FAMS2_GLOBAL_CONTROL_LOCK_FAST; + (*num_steps)++; + } current_pipe = pipe_ctx; while (current_pipe) { @@ -801,6 +835,9 @@ void hwss_execute_sequence(struct dc *dc, case DMUB_SUBVP_SAVE_SURF_ADDR: hwss_subvp_save_surf_addr(params); break; + case DMUB_FAMS2_GLOBAL_CONTROL_LOCK_FAST: + dc->hwss.fams2_global_control_lock_fast(params); + break; default: ASSERT(false); break; @@ -840,6 +877,12 @@ void hwss_setup_dpp(union block_sequence_params *params) plane_state->color_space, NULL); } + + if (dpp && dpp->funcs->set_cursor_matrix) { + dpp->funcs->set_cursor_matrix(dpp, + plane_state->color_space, + plane_state->cursor_csc_color_matrix); + } } void hwss_program_bias_and_scale(union block_sequence_params *params) 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 15819416a2f3..6831b0151705 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -74,6 +74,10 @@ #include "dcn321/dcn321_resource.h" #include "dcn35/dcn35_resource.h" #include "dcn351/dcn351_resource.h" +#include "dcn401/dcn401_resource.h" +#if defined(CONFIG_DRM_AMD_DC_FP) +#include "dc_spl_translate.h" +#endif #define VISUAL_CONFIRM_BASE_DEFAULT 3 #define VISUAL_CONFIRM_BASE_MIN 1 @@ -199,6 +203,10 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) if (ASICREV_IS_GC_11_0_4(asic_id.hw_internal_rev)) dc_version = DCN_VERSION_3_51; break; + case AMDGPU_FAMILY_GC_12_0_0: + if (ASICREV_IS_DCN401(asic_id.hw_internal_rev)) + dc_version = DCN_VERSION_4_01; + break; default: dc_version = DCE_VERSION_UNKNOWN; break; @@ -309,6 +317,9 @@ struct resource_pool *dc_create_resource_pool(struct dc *dc, case DCN_VERSION_3_51: res_pool = dcn351_create_resource_pool(init_data, dc); break; + case DCN_VERSION_4_01: + res_pool = dcn401_create_resource_pool(init_data, dc); + break; #endif /* CONFIG_DRM_AMD_DC_FP */ default: break; @@ -1514,6 +1525,31 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( pipe_ctx->plane_state->format); + if (pipe_ctx->stream->ctx->dc->config.use_spl) { +#if defined(CONFIG_DRM_AMD_DC_FP) + struct spl_in *spl_in = &pipe_ctx->plane_res.spl_in; + struct spl_out *spl_out = &pipe_ctx->plane_res.spl_out; + + if (plane_state->ctx->dce_version > DCE_VERSION_MAX) + pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_36BPP; + else + pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; + + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha; + spl_out->scl_data.h_active = pipe_ctx->plane_res.scl_data.h_active; + spl_out->scl_data.v_active = pipe_ctx->plane_res.scl_data.v_active; + + // Convert pipe_ctx to respective input params for SPL + translate_SPL_in_params_from_pipe_ctx(pipe_ctx, spl_in); + // Set SPL output parameters to dscl_prog_data to be used for hw registers + spl_out->dscl_prog_data = resource_get_dscl_prog_data(pipe_ctx); + // Calculate scaler parameters from SPL + res = spl_calculate_scaler_params(spl_in, spl_out); + // Convert respective out params from SPL to scaler data + translate_SPL_out_params_to_pipe_ctx(pipe_ctx, spl_out); +#endif + } else { + /* depends on h_active */ calculate_recout(pipe_ctx); /* depends on pixel format */ @@ -1593,8 +1629,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.scl_data.viewport.height = MIN_VIEWPORT_SIZE; if (pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE) pipe_ctx->plane_res.scl_data.viewport.width = MIN_VIEWPORT_SIZE; - - + } DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d Recout: height:%d width:%d x:%d y:%d HACTIVE:%d VACTIVE:%d\n" "src_rect: height:%d width:%d x:%d y:%d dst_rect: height:%d width:%d x:%d y:%d clip_rect: height:%d width:%d x:%d y:%d\n", __func__, @@ -5093,6 +5128,11 @@ bool check_subvp_sw_cursor_fallback_req(const struct dc *dc, struct dc_stream_st return false; } +struct dscl_prog_data *resource_get_dscl_prog_data(struct pipe_ctx *pipe_ctx) +{ + return &pipe_ctx->plane_res.scl_data.dscl_prog_data; +} + void resource_init_common_dml2_callbacks(struct dc *dc, struct dml2_configuration_options *dml2_options) { dml2_options->callbacks.dc = dc; 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 76bb05f4d6bf..7f5d5545ae08 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c @@ -33,8 +33,10 @@ #include "resource.h" #include "link_enc_cfg.h" +#if defined(CONFIG_DRM_AMD_DC_FP) #include "dml2/dml2_wrapper.h" #include "dml2/dml2_internal_types.h" +#endif #define DC_LOGGER \ dc->ctx->logger @@ -916,3 +918,17 @@ struct dc_stream_state *dc_state_get_stream_from_id(const struct dc_state *state return stream; } +bool dc_state_is_fams2_in_use( + const struct dc *dc, + const struct dc_state *state) +{ + bool is_fams2_in_use = false; + + if (state) + is_fams2_in_use |= state->bw_ctx.bw.dcn.fams2_stream_count > 0; + + if (dc->current_state) + is_fams2_in_use |= dc->current_state->bw_ctx.bw.dcn.fams2_stream_count > 0; + + return is_fams2_in_use; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 97c78cadb603..9d235fc3525d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -260,7 +260,10 @@ struct dc_caps { bool zstate_support; bool ips_support; uint32_t num_of_internal_disp; + uint32_t max_dwb_htap; + uint32_t max_dwb_vtap; enum dp_protocol_version max_dp_protocol_version; + bool spdif_aud; unsigned int mall_size_per_mem_channel; unsigned int mall_size_total; unsigned int cursor_cache_size; @@ -286,6 +289,7 @@ struct dc_caps { uint32_t max_v_total; uint32_t max_disp_clock_khz_at_vmin; uint8_t subvp_drr_vblank_start_margin_us; + bool cursor_not_scaled; }; struct dc_bug_wa { @@ -299,11 +303,19 @@ struct dc_bug_wa { uint8_t dcfclk : 1; uint8_t dcfclk_ds: 1; } clock_update_disable_mask; + //Customer Specific WAs + uint32_t force_backlight_start_level; }; struct dc_dcc_surface_param { struct dc_size surface_size; enum surface_pixel_format format; - enum swizzle_mode_values swizzle_mode; + unsigned int plane0_pitch; + struct dc_size plane1_size; + unsigned int plane1_pitch; + union { + enum swizzle_mode_values swizzle_mode; + enum swizzle_mode_addr3_values swizzle_mode_addr3; + }; enum dc_scan_direction scan; }; @@ -384,7 +396,6 @@ struct dc; struct dc_plane_state; struct dc_state; - struct dc_cap_funcs { bool (*get_dcc_compression_cap)(const struct dc *dc, const struct dc_dcc_surface_param *input, @@ -427,6 +438,8 @@ struct dc_config { bool is_asymmetric_memory; bool is_single_rank_dimm; bool is_vmin_only_asic; + bool use_spl; + bool prefer_easf; bool use_pipe_ctx_sync_logic; bool ignore_dpref_ss; bool enable_mipi_converter_optimization; @@ -457,6 +470,7 @@ enum visual_confirm { VISUAL_CONFIRM_REPLAY = 12, VISUAL_CONFIRM_SUBVP = 14, VISUAL_CONFIRM_MCLK_SWITCH = 16, + VISUAL_CONFIRM_FAMS2 = 19, }; enum dc_psr_power_opts { @@ -970,6 +984,7 @@ struct dc_debug_options { bool enable_single_display_2to1_odm_policy; bool enable_double_buffered_dsc_pg_support; bool enable_dp_dig_pixel_rate_div_policy; + bool using_dml21; enum lttpr_mode lttpr_mode_override; unsigned int dsc_delay_factor_wa_x1000; unsigned int min_prefetch_in_strobe_ns; @@ -1005,6 +1020,10 @@ struct dc_debug_options { unsigned int static_screen_wait_frames; bool force_chroma_subsampling_1tap; bool disable_422_left_edge_pixel; + bool dml21_force_pstate_method; + uint32_t dml21_force_pstate_method_value; + uint32_t dml21_disable_pstate_method_mask; + union dmub_fams2_global_feature_config fams2_config; unsigned int force_cositing; }; @@ -1214,6 +1233,7 @@ union surface_update_flags { uint32_t stereo_format_change:1; uint32_t lut_3d:1; uint32_t tmz_changed:1; + uint32_t mcm_transfer_function_enable_change:1; /* disable or enable MCM transfer func */ uint32_t full_update:1; } bits; @@ -1288,6 +1308,15 @@ 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; + unsigned int sharpnessX1000; + enum linear_light_scaling linear_light_scaling; }; struct dc_plane_info { @@ -1306,6 +1335,7 @@ struct dc_plane_info { int global_alpha_value; bool input_csc_enabled; int layer_index; + bool front_buffer_rendering_active; enum chroma_cositing cositing; }; @@ -1413,6 +1443,7 @@ struct dc_fast_update { const struct fixed31_32 *coeff_reduction_factor; struct dc_transfer_func *out_transfer_func; struct dc_csc_transform *output_csc_transform; + const struct dc_csc_transform *cursor_csc_color_matrix; }; struct dc_surface_update { @@ -1435,6 +1466,14 @@ struct dc_surface_update { const struct dc_3dlut *lut3d_func; const struct dc_transfer_func *blend_tf; const struct colorspace_transform *gamut_remap_matrix; + /* + * Color Transformations for pre-blend MCM (Shaper, 3DLUT, 1DLUT) + * + * change cm2_params.component_settings: Full update + * change cm2_params.cm2_luts: Fast update + */ + struct dc_cm2_parameters *cm2_params; + const struct dc_csc_transform *cursor_csc_color_matrix; }; /* @@ -1531,6 +1570,7 @@ struct dc_plane_state *dc_get_surface_for_mpcc(struct dc *dc, uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane); void dc_set_disable_128b_132b_stream_overhead(bool disable); +bool dc_get_disable_128b_132b_stream_overhead(void); /* The function returns minimum bandwidth required to drive a given timing * return - minimum required timing bandwidth in kbps. @@ -1660,7 +1700,6 @@ struct dc_link { union dpcd_sink_ext_caps dpcd_sink_ext_caps; struct psr_settings psr_settings; - struct replay_settings replay_settings; /* Drive settings read from integrated info table */ 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 26940d94d8fb..5fa5e2b63fb7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -183,6 +183,7 @@ struct dc_bios { struct dc_firmware_info fw_info; bool fw_info_valid; struct dc_vram_info vram_info; + struct bp_soc_bb_info bb_info; struct dc_golden_table golden_table; }; 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 2293a92df3be..3177000335b2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -1595,3 +1595,179 @@ bool dc_wake_and_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_com return result; } +void dc_dmub_srv_fams2_update_config(struct dc *dc, + struct dc_state *context, + bool enable) +{ + uint8_t num_cmds = 1; + uint32_t i; + union dmub_rb_cmd cmd[MAX_STREAMS + 1]; + struct dmub_rb_cmd_fams2 *global_cmd = &cmd[0].fams2_config; + + memset(cmd, 0, sizeof(union dmub_rb_cmd) * (MAX_STREAMS + 1)); + /* fill in generic command header */ + global_cmd->header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH; + global_cmd->header.sub_type = DMUB_CMD__FAMS2_CONFIG; + global_cmd->header.payload_bytes = sizeof(struct dmub_rb_cmd_fams2) - sizeof(struct dmub_cmd_header); + + /* send global configuration parameters */ + global_cmd->config.global.max_allow_delay_us = 100 * 1000; //100ms + global_cmd->config.global.lock_wait_time_us = 5000; //5ms + + /* copy static feature configuration */ + global_cmd->config.global.features.all = dc->debug.fams2_config.all; + + /* apply feature configuration based on current driver state */ + global_cmd->config.global.features.bits.enable_visual_confirm = dc->debug.visual_confirm == VISUAL_CONFIRM_FAMS2; + global_cmd->config.global.features.bits.enable = enable; + + /* construct per-stream configs */ + if (enable) { + for (i = 0; i < context->bw_ctx.bw.dcn.fams2_stream_count; i++) { + struct dmub_rb_cmd_fams2 *stream_cmd = &cmd[i+1].fams2_config; + + /* configure command header */ + stream_cmd->header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH; + stream_cmd->header.sub_type = DMUB_CMD__FAMS2_CONFIG; + stream_cmd->header.payload_bytes = sizeof(struct dmub_rb_cmd_fams2) - sizeof(struct dmub_cmd_header); + stream_cmd->header.multi_cmd_pending = 1; + /* copy stream static state */ + memcpy(&stream_cmd->config.stream, + &context->bw_ctx.bw.dcn.fams2_stream_params[i], + sizeof(struct dmub_fams2_stream_static_state)); + } + } + + if (enable && context->bw_ctx.bw.dcn.fams2_stream_count) { + /* set multi pending for global, and unset for last stream cmd */ + global_cmd->config.global.num_streams = context->bw_ctx.bw.dcn.fams2_stream_count; + global_cmd->header.multi_cmd_pending = 1; + cmd[context->bw_ctx.bw.dcn.fams2_stream_count].fams2_config.header.multi_cmd_pending = 0; + num_cmds += context->bw_ctx.bw.dcn.fams2_stream_count; + } + + dm_execute_dmub_cmd_list(dc->ctx, num_cmds, cmd, DM_DMUB_WAIT_TYPE_WAIT); +} + +void dc_dmub_srv_fams2_drr_update(struct dc *dc, + uint32_t tg_inst, + uint32_t vtotal_min, + uint32_t vtotal_max, + uint32_t vtotal_mid, + uint32_t vtotal_mid_frame_num, + bool program_manual_trigger) +{ + union dmub_rb_cmd cmd = { 0 }; + + cmd.fams2_drr_update.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH; + cmd.fams2_drr_update.header.sub_type = DMUB_CMD__FAMS2_DRR_UPDATE; + cmd.fams2_drr_update.dmub_optc_state_req.tg_inst = tg_inst; + cmd.fams2_drr_update.dmub_optc_state_req.v_total_max = vtotal_max; + cmd.fams2_drr_update.dmub_optc_state_req.v_total_min = vtotal_min; + cmd.fams2_drr_update.dmub_optc_state_req.v_total_mid = vtotal_mid; + cmd.fams2_drr_update.dmub_optc_state_req.v_total_mid_frame_num = vtotal_mid_frame_num; + cmd.fams2_drr_update.dmub_optc_state_req.program_manual_trigger = program_manual_trigger; + + cmd.fams2_drr_update.header.payload_bytes = sizeof(cmd.fams2_drr_update) - sizeof(cmd.fams2_drr_update.header); + + dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT); +} + +void dc_dmub_srv_fams2_passthrough_flip( + struct dc *dc, + struct dc_state *state, + struct dc_stream_state *stream, + struct dc_surface_update *srf_updates, + int surface_count) +{ + int plane_index; + union dmub_rb_cmd cmds[MAX_PLANES]; + struct dc_plane_address *address; + struct dc_plane_state *plane_state; + int num_cmds = 0; + struct dc_stream_status *stream_status = dc_stream_get_status(stream); + + if (surface_count <= 0 || stream_status == NULL) + return; + + memset(cmds, 0, sizeof(union dmub_rb_cmd) * MAX_PLANES); + + /* build command for each surface update */ + for (plane_index = 0; plane_index < surface_count; plane_index++) { + plane_state = srf_updates[plane_index].surface; + address = &plane_state->address; + + /* skip if there is no address update for plane */ + if (!srf_updates[plane_index].flip_addr) + continue; + + /* build command header */ + cmds[num_cmds].fams2_flip.header.type = DMUB_CMD__FW_ASSISTED_MCLK_SWITCH; + cmds[num_cmds].fams2_flip.header.sub_type = DMUB_CMD__FAMS2_FLIP; + cmds[num_cmds].fams2_flip.header.payload_bytes = sizeof(struct dmub_rb_cmd_fams2_flip); + + /* for chaining multiple commands, all but last command should set to 1 */ + cmds[num_cmds].fams2_flip.header.multi_cmd_pending = 1; + + /* set topology info */ + cmds[num_cmds].fams2_flip.flip_info.pipe_mask = dc_plane_get_pipe_mask(state, plane_state); + if (stream_status) + cmds[num_cmds].fams2_flip.flip_info.otg_inst = stream_status->primary_otg_inst; + + cmds[num_cmds].fams2_flip.flip_info.config.bits.is_immediate = plane_state->flip_immediate; + + /* build address info for command */ + switch (address->type) { + case PLN_ADDR_TYPE_GRAPHICS: + if (address->grph.addr.quad_part == 0) { + BREAK_TO_DEBUGGER(); + break; + } + + cmds[num_cmds].fams2_flip.flip_info.addr_info.meta_addr_lo = + address->grph.meta_addr.low_part; + cmds[num_cmds].fams2_flip.flip_info.addr_info.meta_addr_hi = + (uint16_t)address->grph.meta_addr.high_part; + cmds[num_cmds].fams2_flip.flip_info.addr_info.surf_addr_lo = + address->grph.addr.low_part; + cmds[num_cmds].fams2_flip.flip_info.addr_info.surf_addr_hi = + (uint16_t)address->grph.addr.high_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_TO_DEBUGGER(); + break; + } + + cmds[num_cmds].fams2_flip.flip_info.addr_info.meta_addr_lo = + address->video_progressive.luma_meta_addr.low_part; + cmds[num_cmds].fams2_flip.flip_info.addr_info.meta_addr_hi = + (uint16_t)address->video_progressive.luma_meta_addr.high_part; + cmds[num_cmds].fams2_flip.flip_info.addr_info.meta_addr_c_lo = + address->video_progressive.chroma_meta_addr.low_part; + cmds[num_cmds].fams2_flip.flip_info.addr_info.meta_addr_c_hi = + (uint16_t)address->video_progressive.chroma_meta_addr.high_part; + cmds[num_cmds].fams2_flip.flip_info.addr_info.surf_addr_lo = + address->video_progressive.luma_addr.low_part; + cmds[num_cmds].fams2_flip.flip_info.addr_info.surf_addr_hi = + (uint16_t)address->video_progressive.luma_addr.high_part; + cmds[num_cmds].fams2_flip.flip_info.addr_info.surf_addr_c_lo = + address->video_progressive.chroma_addr.low_part; + cmds[num_cmds].fams2_flip.flip_info.addr_info.surf_addr_c_hi = + (uint16_t)address->video_progressive.chroma_addr.high_part; + break; + default: + // Should never be hit + BREAK_TO_DEBUGGER(); + break; + } + + num_cmds++; + } + + if (num_cmds > 0) { + cmds[num_cmds - 1].fams2_flip.header.multi_cmd_pending = 0; + dm_execute_dmub_cmd_list(dc->ctx, num_cmds, cmds, DM_DMUB_WAIT_TYPE_WAIT); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h index 2c5866211f60..72cc483e1556 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h @@ -74,7 +74,7 @@ bool dc_dmub_srv_cmd_run(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd bool dc_dmub_srv_cmd_run_list(struct dc_dmub_srv *dc_dmub_srv, unsigned int count, union dmub_rb_cmd *cmd_list, enum dm_dmub_wait_type wait_type); bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv, - unsigned int stream_mask); + unsigned int stream_mask); bool dc_dmub_srv_is_restore_required(struct dc_dmub_srv *dc_dmub_srv); @@ -160,4 +160,20 @@ bool dc_wake_and_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned in bool dc_wake_and_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_command command_code, uint16_t param, uint32_t *response, enum dm_dmub_wait_type wait_type); +void dc_dmub_srv_fams2_update_config(struct dc *dc, + struct dc_state *context, + bool enable); +void dc_dmub_srv_fams2_drr_update(struct dc *dc, + uint32_t tg_inst, + uint32_t vtotal_min, + uint32_t vtotal_max, + uint32_t vtotal_mid, + uint32_t vtotal_mid_frame_num, + bool program_manual_trigger); +void dc_dmub_srv_fams2_passthrough_flip( + struct dc *dc, + struct dc_state *state, + struct dc_stream_state *stream, + struct dc_surface_update *srf_updates, + int surface_count); #endif /* _DMUB_DC_SRV_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_helper.c b/drivers/gpu/drm/amd/display/dc/dc_helper.c index 8f9a67825615..514c244d8464 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dc_helper.c @@ -266,7 +266,6 @@ uint32_t generic_reg_set_ex(const struct dc_context *ctx, va_end(ap); - /* mmio write directly */ reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value; @@ -747,6 +746,8 @@ char *dce_version_to_string(const int version) return "DCN 3.5"; case DCN_VERSION_3_51: return "DCN 3.5.1"; + case DCN_VERSION_4_01: + return "DCN 4.0.1"; 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 2ad7f60805f5..226285037b2b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -60,6 +60,7 @@ union large_integer { enum dc_plane_addr_type { PLN_ADDR_TYPE_GRAPHICS = 0, + PLN_ADDR_TYPE_3DLUT, PLN_ADDR_TYPE_GRPH_STEREO, PLN_ADDR_TYPE_VIDEO_PROGRESSIVE, PLN_ADDR_TYPE_RGBEA @@ -76,6 +77,10 @@ struct dc_plane_address { union large_integer dcc_const_color; } grph; + struct { + PHYSICAL_ADDRESS_LOC addr; + } lut3d; + /*stereo*/ struct { PHYSICAL_ADDRESS_LOC left_addr; @@ -93,7 +98,6 @@ struct dc_plane_address { PHYSICAL_ADDRESS_LOC right_alpha_addr; PHYSICAL_ADDRESS_LOC right_alpha_meta_addr; union large_integer right_alpha_dcc_const_color; - } grph_stereo; /*video progressive*/ @@ -121,6 +125,9 @@ struct dc_plane_address { union large_integer page_table_base; uint8_t vmid; + /* dc should use hw flip queue rather than directly programming the surface address. + * Value is determined on each flip. */ + bool offload_flip; }; struct dc_size { @@ -263,6 +270,9 @@ enum tripleBuffer_enable { DC_TRIPLEBUFFER_DISABLE = 0x0, DC_TRIPLEBUFFER_ENABLE = 0x1, }; +enum tile_split_values_new { + DC_SURF_TILE_SPLIT_1KB = 0x4, +}; /* TODO: These values come from hardware spec. We need to readdress this * if they ever change. @@ -320,6 +330,20 @@ enum swizzle_mode_values { DC_SW_UNKNOWN = DC_SW_MAX }; +// Definition of swizzle modes with addr3 ASICs +enum swizzle_mode_addr3_values { + DC_ADDR3_SW_LINEAR = 0, + DC_ADDR3_SW_256B_2D = 1, + DC_ADDR3_SW_4KB_2D = 2, + DC_ADDR3_SW_64KB_2D = 3, + DC_ADDR3_SW_256KB_2D = 4, + DC_ADDR3_SW_4KB_3D = 5, + DC_ADDR3_SW_64KB_3D = 6, + DC_ADDR3_SW_256KB_3D = 7, + DC_ADDR3_SW_MAX = 8, + DC_ADDR3_SW_UNKNOWN = DC_ADDR3_SW_MAX +}; + union dc_tiling_info { struct { @@ -399,7 +423,10 @@ union dc_tiling_info { bool rb_aligned; bool pipe_aligned; unsigned int num_pkrs; - } gfx9; + } gfx9;/*gfx9, gfx10 and above*/ + struct { + enum swizzle_mode_addr3_values swizzle; + } gfx_addr3;/*gfx with addr3 and above*/ }; /* Rotation angle */ @@ -461,6 +488,7 @@ struct dc_cursor_mi_param { unsigned int pixel_clk_khz; unsigned int ref_clk_khz; struct rect viewport; + struct rect recout; struct fixed31_32 h_scale_ratio; struct fixed31_32 v_scale_ratio; enum dc_rotation_angle rotation; @@ -1058,6 +1086,24 @@ enum cm_gamut_coef_format { CM_GAMUT_REMAP_COEF_FORMAT_S3_12 = 1 }; +enum mpcc_gamut_remap_mode_select { + MPCC_GAMUT_REMAP_MODE_SELECT_0 = 0, + MPCC_GAMUT_REMAP_MODE_SELECT_1, + MPCC_GAMUT_REMAP_MODE_SELECT_2 +}; + +enum mpcc_gamut_remap_id { + MPCC_OGAM_GAMUT_REMAP, + MPCC_MCM_FIRST_GAMUT_REMAP, + MPCC_MCM_SECOND_GAMUT_REMAP +}; + +enum cursor_matrix_mode { + CUR_MATRIX_BYPASS = 0, + CUR_MATRIX_SET_A, + CUR_MATRIX_SET_B +}; + struct mcif_warmup_params { union large_integer start_address; unsigned int address_increment; diff --git a/drivers/gpu/drm/amd/display/dc/dc_state_priv.h b/drivers/gpu/drm/amd/display/dc/dc_state_priv.h index 615086d74d32..1a12ef579ff4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_state_priv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_state_priv.h @@ -101,4 +101,8 @@ void dc_state_release_phantom_streams_and_planes( const struct dc *dc, struct dc_state *state); +bool dc_state_is_fams2_in_use( + const struct dc *dc, + const struct dc_state *state); + #endif /* _DC_STATE_PRIV_H_ */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 0f66d00ef80f..6c85ca3b1e1a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -1172,6 +1172,83 @@ enum dc_hpd_enable_select { HPD_EN_FOR_SECONDARY_EDP_ONLY, }; +enum dc_cm2_shaper_3dlut_setting { + DC_CM2_SHAPER_3DLUT_SETTING_BYPASS_ALL, + DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER, + /* Bypassing Shaper will always bypass 3DLUT */ + DC_CM2_SHAPER_3DLUT_SETTING_ENABLE_SHAPER_3DLUT +}; + +enum dc_cm2_gpu_mem_layout { + DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_RGB, + DC_CM2_GPU_MEM_LAYOUT_3D_SWIZZLE_LINEAR_BGR, + DC_CM2_GPU_MEM_LAYOUT_1D_PACKED_LINEAR +}; + +enum dc_cm2_gpu_mem_pixel_component_order { + DC_CM2_GPU_MEM_PIXEL_COMPONENT_ORDER_RGBA, +}; + +enum dc_cm2_gpu_mem_format { + DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12MSB, + DC_CM2_GPU_MEM_FORMAT_16161616_UNORM_12LSB, + DC_CM2_GPU_MEM_FORMAT_16161616_FLOAT_FP1_5_10 +}; + +struct dc_cm2_gpu_mem_format_parameters { + enum dc_cm2_gpu_mem_format format; + union { + struct { + /* bias & scale for float only */ + uint16_t bias; + uint16_t scale; + } float_params; + }; +}; + +enum dc_cm2_gpu_mem_size { + DC_CM2_GPU_MEM_SIZE_171717, + DC_CM2_GPU_MEM_SIZE_TRANSFORMED +}; + +struct dc_cm2_gpu_mem_parameters { + struct dc_plane_address addr; + enum dc_cm2_gpu_mem_layout layout; + struct dc_cm2_gpu_mem_format_parameters format_params; + enum dc_cm2_gpu_mem_pixel_component_order component_order; + enum dc_cm2_gpu_mem_size size; +}; + +enum dc_cm2_transfer_func_source { + DC_CM2_TRANSFER_FUNC_SOURCE_SYSMEM, + DC_CM2_TRANSFER_FUNC_SOURCE_VIDMEM +}; + +struct dc_cm2_component_settings { + enum dc_cm2_shaper_3dlut_setting shaper_3dlut_setting; + bool lut1d_enable; +}; + +/* + * All pointers in this struct must remain valid for as long as the 3DLUTs are used + */ +struct dc_cm2_func_luts { + const struct dc_transfer_func *shaper; + struct { + enum dc_cm2_transfer_func_source lut3d_src; + union { + const struct dc_3dlut *lut3d_func; + struct dc_cm2_gpu_mem_parameters gpu_mem_params; + }; + } lut3d_data; + const struct dc_transfer_func *lut1d_func; +}; + +struct dc_cm2_parameters { + struct dc_cm2_component_settings component_settings; + struct dc_cm2_func_luts cm2_luts; +}; + enum mall_stream_type { SUBVP_NONE, // subvp not in use SUBVP_MAIN, // subvp in use, this stream is main stream 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 b5e0289d2fe8..6b33117ab5fc 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 @@ -1063,6 +1063,101 @@ static bool dcn31_program_pix_clk( return true; } +static bool dcn401_program_pix_clk( + struct clock_source *clock_source, + struct pixel_clk_params *pix_clk_params, + enum dp_link_encoding encoding, + struct pll_settings *pll_settings) +{ + 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 = + look_up_in_video_optimized_rate_tlb(pix_clk_params->requested_pix_clk_100hz / 10); + struct bp_pixel_clock_parameters bp_pc_params = {0}; + enum transmitter_color_depth bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; + struct dp_dto_params dto_params = { 0 }; + + dto_params.otg_inst = inst; + dto_params.signal = pix_clk_params->signal_type; + + // all but TMDS gets Driver to program DP_DTO without calling VBIOS Command table + if (!dc_is_hdmi_tmds_signal(pix_clk_params->signal_type)) { + long long ref_dtbclk_khz = clock_source->ctx->dc->clk_mgr->funcs->get_dtb_ref_clk_frequency(clock_source->ctx->dc->clk_mgr); + long long dprefclk_khz = clock_source->ctx->dc->clk_mgr->dprefclk_khz; + long long dtbclk_p_src_clk_khz; + /* if signal is DP132B128B dtbclk_p_src is DTBCLK else DPREFCLK */ + dtbclk_p_src_clk_khz = encoding == DP_128b_132b_ENCODING ? ref_dtbclk_khz : dprefclk_khz; + if (e) { + dto_params.pixclk_hz = e->target_pixel_rate_khz * e->mult_factor; + dto_params.refclk_hz = dtbclk_p_src_clk_khz * e->div_factor; + } else { + dto_params.pixclk_hz = pix_clk_params->requested_pix_clk_100hz * 100; + dto_params.refclk_hz = dtbclk_p_src_clk_khz * 1000; + } + + /* enable DP DTO */ + clock_source->ctx->dc->res_pool->dccg->funcs->set_dp_dto( + clock_source->ctx->dc->res_pool->dccg, + &dto_params); + + } else { + /* disables DP DTO when provided with TMDS signal type */ + clock_source->ctx->dc->res_pool->dccg->funcs->set_dp_dto( + clock_source->ctx->dc->res_pool->dccg, + &dto_params); + + /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/ + bp_pc_params.controller_id = pix_clk_params->controller_id; + bp_pc_params.pll_id = clock_source->id; + bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz; + bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; + bp_pc_params.signal_type = pix_clk_params->signal_type; + + // Make sure we send the correct color depth to DMUB for HDMI + if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) { + switch (pix_clk_params->color_depth) { + case COLOR_DEPTH_888: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; + break; + case COLOR_DEPTH_101010: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_30; + break; + case COLOR_DEPTH_121212: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_36; + break; + case COLOR_DEPTH_161616: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_48; + break; + default: + bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; + break; + } + bp_pc_params.color_depth = bp_pc_colour_depth; + } + + if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) { + bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC = + pll_settings->use_external_clk; + bp_pc_params.flags.SET_XTALIN_REF_SRC = + !pll_settings->use_external_clk; + if (pix_clk_params->flags.SUPPORT_YCBCR420) { + bp_pc_params.flags.SUPPORT_YUV_420 = 1; + } + } + if (clk_src->bios->funcs->set_pixel_clock( + clk_src->bios, &bp_pc_params) != BP_RESULT_OK) + return false; + /* Resync deep color DTO */ + if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) + dce112_program_pixel_clk_resync(clk_src, + pix_clk_params->signal_type, + pix_clk_params->color_depth, + pix_clk_params->flags.SUPPORT_YCBCR420); + } + + return true; +} + static bool dce110_clock_source_power_down( struct clock_source *clk_src) { @@ -1314,6 +1409,13 @@ static const struct clock_source_funcs dcn31_clk_src_funcs = { .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz }; +static const struct clock_source_funcs dcn401_clk_src_funcs = { + .cs_power_down = dce110_clock_source_power_down, + .program_pix_clk = dcn401_program_pix_clk, + .get_pix_clk_dividers = dcn3_get_pix_clk_dividers, + .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz +}; + /*****************************************/ /* Constructor */ /*****************************************/ @@ -1731,6 +1833,21 @@ bool dcn31_clk_src_construct( return ret; } +bool dcn401_clk_src_construct( + struct dce110_clk_src *clk_src, + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + const struct dce110_clk_src_shift *cs_shift, + const struct dce110_clk_src_mask *cs_mask) +{ + bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask); + + clk_src->base.funcs = &dcn401_clk_src_funcs; + + return ret; +} bool dcn301_clk_src_construct( struct dce110_clk_src *clk_src, struct dc_context *ctx, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h index f600b7431e23..0721ae895ae9 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.h @@ -307,6 +307,14 @@ bool dcn31_clk_src_construct( const struct dce110_clk_src_shift *cs_shift, const struct dce110_clk_src_mask *cs_mask); +bool dcn401_clk_src_construct( + struct dce110_clk_src *clk_src, + struct dc_context *ctx, + struct dc_bios *bios, + enum clock_source_id id, + const struct dce110_clk_src_regs *regs, + const struct dce110_clk_src_shift *cs_shift, + const struct dce110_clk_src_mask *cs_mask); /* this table is use to find *1.001 and /1.001 pixel rates from non-precise pixel rate */ struct pixel_rate_range_table_entry { unsigned int range_min_khz; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h index 3da32217d9ec..a9a16f645994 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_i2c_hw.h @@ -249,6 +249,10 @@ struct dce_i2c_mask { I2C_COMMON_MASK_SH_LIST_DCN30(mask_sh),\ I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_EN, mask_sh) +#define I2C_COMMON_MASK_SH_LIST_DCN401(mask_sh)\ + I2C_COMMON_MASK_SH_LIST_DCN30(mask_sh),\ + I2C_SF(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_EN, mask_sh) + struct dce_i2c_registers { uint32_t SETUP; uint32_t SPEED; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h index d4438c011284..54a6a4ebd636 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h @@ -596,8 +596,8 @@ struct dcn10_stream_enc_registers { #define SE_REG_FIELD_LIST_DCN4_01_COMMON(type) \ type COMPRESSED_PIXEL_FORMAT;\ type DP_VID_N_INTERVAL;\ - type DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE - + type DIG_FIFO_OUTPUT_PIXEL_PER_CYCLE;\ + type DP_STEER_FIFO_ENABLE struct dcn10_stream_encoder_shift { SE_REG_FIELD_LIST_DCN1_0(uint8_t); uint8_t HDMI_ACP_SEND; diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c index fca94e50ae93..3aeb85ec40b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c @@ -1492,7 +1492,7 @@ static void mpc3_read_mpcc_state( MPC_RMU_3DLUT_SIZE, &s->lut3d_size); } - REG_GET_2(MPCC_OGAM_CONTROL[mpcc_inst], + REG_GET_2(MPCC_OGAM_CONTROL[mpcc_inst], MPCC_OGAM_MODE_CURRENT, &s->rgam_mode, MPCC_OGAM_SELECT_CURRENT, &s->rgam_lut); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h index ce93003dae01..54f889cfd911 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h @@ -1091,6 +1091,10 @@ void mpc3_power_on_ogam_lut( void mpc3_init_mpcc(struct mpcc *mpcc, int mpcc_inst); +void mpc3_mpc_init_single_inst( + struct mpc *mpc, + unsigned int mpcc_id); + enum dc_lut_mode mpc3_get_ogam_current( struct mpc *mpc, int mpcc_id); diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c index 515c4c2b4c21..5264dc26cce1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c @@ -128,7 +128,7 @@ void dcn32_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigned int d } } -static void dcn32_program_compbuf_size(struct hubbub *hubbub, unsigned int compbuf_size_kb, bool safe_to_increase) +void dcn32_program_compbuf_size(struct hubbub *hubbub, unsigned int compbuf_size_kb, bool safe_to_increase) { struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub); unsigned int compbuf_size_segments = (compbuf_size_kb + DCN32_CRB_SEGMENT_SIZE_KB - 1) / DCN32_CRB_SEGMENT_SIZE_KB; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h index e439ba0fa30f..bfc55dbbad1f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h @@ -161,4 +161,6 @@ void hubbub32_set_request_limit(struct hubbub *hubbub, int umc_count, int words_ void hubbub32_get_mall_en(struct hubbub *hubbub, unsigned int *mall_in_use); +void dcn32_program_compbuf_size(struct hubbub *hubbub, unsigned int compbuf_size_kb, bool safe_to_increase); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c index e408e859b355..a0e9e9f0441a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c @@ -30,6 +30,7 @@ #include "basics/conversion.h" #include "dcn10/dcn10_cm_common.h" #include "dc.h" +#include "dcn401/dcn401_mpc.h" #define REG(reg)\ mpc30->mpc_regs->reg @@ -1017,6 +1018,8 @@ static const struct mpc_funcs dcn32_mpc_funcs = { .power_on_mpc_mem_pwr = mpc3_power_on_ogam_lut, .get_mpc_out_mux = mpc1_get_mpc_out_mux, .set_bg_color = mpc1_set_bg_color, + .set_movable_cm_location = mpc401_set_movable_cm_location, + .populate_lut = mpc401_populate_lut, }; diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index c4a5efd2dda5..0f7f1941aa54 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -140,6 +140,9 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calcs.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_auto.o := $(dml_rcflags) CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_math.o := $(dml_rcflags) +CFLAGS_$(AMDDALPATH)/dc/dml/dcn401/dcn401_fpu.o := $(dml_ccflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn401/dcn401_fpu.o := $(dml_rcflags) + ifdef CONFIG_DRM_AMD_DC_FP DML += display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o DML += dcn10/dcn10_fpu.o @@ -160,6 +163,7 @@ DML += dcn303/dcn303_fpu.o DML += dcn314/dcn314_fpu.o DML += dcn35/dcn35_fpu.o DML += dcn351/dcn351_fpu.o +DML += dcn401/dcn401_fpu.o DML += dsc/rc_calc_fpu.o DML += calcs/dcn_calcs.o calcs/dcn_calc_math.o calcs/dcn_calc_auto.o endif 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 3242957d00c5..f52b9e3d2bee 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 @@ -24,10 +24,7 @@ * */ -#define UNIT_TEST 0 -#if !UNIT_TEST #include "dc.h" -#endif #include "../display_mode_lib.h" #include "display_mode_vba_314.h" #include "../dml_inline_defs.h" diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h index fb17f8868cb4..410e4b671228 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_structs.h @@ -632,6 +632,7 @@ struct _vcs_dpi_display_dlg_regs_st { unsigned int ref_freq_to_pix_freq; unsigned int vratio_prefetch; unsigned int vratio_prefetch_c; + unsigned int refcyc_per_tdlut_group; unsigned int refcyc_per_pte_group_vblank_l; unsigned int refcyc_per_pte_group_vblank_c; unsigned int refcyc_per_meta_chunk_vblank_l; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/Makefile b/drivers/gpu/drm/amd/display/dc/dml2/Makefile index 1c9498a72520..6c76f346b237 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml2/Makefile @@ -67,7 +67,18 @@ frame_warn_flag := -Wframe-larger-than=2048 endif endif +# DRIVER_BUILD is mostly used in DML2.1 source +subdir-ccflags-y += -DDRIVER_BUILD=1 subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2 +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2/dml21/src/dml2_core +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2/dml21/src/dml2_mcg/ +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2/dml21/src/dml2_dpmm/ +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2/dml21/src/dml2_pmo/ +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2/dml21/src/dml2_standalone_libraries/ +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2/dml21/src/inc +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2/dml21/inc +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2/dml21/ + CFLAGS_$(AMDDALPATH)/dc/dml2/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag) CFLAGS_$(AMDDALPATH)/dc/dml2/display_mode_util.o := $(dml2_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml2/dml2_wrapper.o := $(dml2_ccflags) @@ -96,3 +107,72 @@ AMD_DAL_DML2 = $(addprefix $(AMDDALPATH)/dc/dml2/,$(DML2)) AMD_DISPLAY_FILES += $(AMD_DAL_DML2) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_top/dml_top.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_top/dml_top_mcache.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_top/dml2_top_optimization := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_ccflags) -Wframe-larger-than=2048 +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_core/dml2_core_factory.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_core/dml2_core_shared.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_factory.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_dcn4.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_factory.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_factory.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_standalone_libraries/lib_float_math.o := $(dml2_ccflags) + + +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/src/dml21_wrapper.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/dml21_translation_helper.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/dml21_utils.o := $(dml2_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml2/dml21/inc/dml2_debug.o := $(dml2_ccflags) + +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_top/dml_top.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_top/dml_top_mcache.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_top/dml2_top_optimization.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.o := $(dml2_rcflags) -Wframe-larger-than=2048 +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_core/dml2_core_factory.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_core/dml2_core_shared.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_dcn4.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_dpmm/dml2_dpmm_factory.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_dcn4.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_mcg/dml2_mcg_factory.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn3.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_dcn4_fams2.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_pmo/dml2_pmo_factory.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml2_standalone_libraries/lib_float_math.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/src/dml21_wrapper.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/dml21_translation_helper.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/dml21_utils.o := $(dml2_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml2/dml21/inc/dml2_debug.o := $(dml2_rcflags) + +DML21 := src/dml2_top/dml_top.o +DML21 += src/dml2_top/dml_top_mcache.o +DML21 += src/dml2_top/dml2_top_optimization.o +DML21 += src/inc/dml2_debug.o +DML21 += src/dml2_core/dml2_core_dcn4.o +DML21 += src/dml2_core/dml2_core_factory.o +DML21 += src/dml2_core/dml2_core_dcn4_calcs.o +DML21 += src/dml2_core/dml2_core_shared.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_factory.o +DML21 += src/dml2_pmo/dml2_pmo_dcn3.o +DML21 += src/dml2_pmo/dml2_pmo_dcn4.o +DML21 += src/dml2_pmo/dml2_pmo_factory.o +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_utils.o + +AMD_DAL_DML21 = $(addprefix $(AMDDALPATH)/dc/dml2/dml21/,$(DML21)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DML21) + diff --git a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core_structs.h b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core_structs.h index b274bfb4225f..f595e48ae7b8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core_structs.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core_structs.h @@ -36,6 +36,7 @@ enum dml_project_id { dml_project_dcn321 = 2, dml_project_dcn35 = 3, dml_project_dcn351 = 4, + dml_project_dcn401 = 5, }; enum dml_prefetch_modes { dml_prefetch_support_uclk_fclk_and_stutter_if_possible = 0, diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c index ad2a6b4769fe..507cff525f97 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c @@ -812,6 +812,25 @@ static unsigned int get_target_mpc_factor(struct dml2_context *ctx, stream->stream_id, plane_idx, &plane_id); cfg_idx = find_disp_cfg_idx_by_plane_id(mapping, plane_id); mpc_factor = (unsigned int)disp_cfg->hw.DPPPerSurface[cfg_idx]; + } else if (ctx->architecture == dml2_architecture_21) { + if (ctx->config.svp_pstate.callbacks.get_stream_subvp_type(state, stream) == SUBVP_PHANTOM) { + struct dc_stream_state *main_stream; + struct dc_stream_status *main_stream_status; + + /* get stream id of main stream */ + main_stream = ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(state, stream); + main_stream_status = ctx->config.callbacks.get_stream_status(state, main_stream); + + /* get plane id for associated main plane */ + get_plane_id(ctx, state, main_stream_status->plane_states[plane_idx], + main_stream->stream_id, plane_idx, &plane_id); + } else { + get_plane_id(ctx, state, status->plane_states[plane_idx], + stream->stream_id, plane_idx, &plane_id); + } + + cfg_idx = find_disp_cfg_idx_by_plane_id(mapping, plane_id); + mpc_factor = ctx->v21.mode_programming.programming->plane_programming[cfg_idx].num_dpps_required; } else { mpc_factor = 1; ASSERT(false); @@ -847,6 +866,24 @@ static unsigned int get_target_odm_factor( break; } } + else if (ctx->architecture == dml2_architecture_21) { + if (ctx->config.svp_pstate.callbacks.get_stream_subvp_type(state, stream) == SUBVP_PHANTOM) { + struct dc_stream_state *main_stream; + + /* get stream id of main stream */ + main_stream = ctx->config.svp_pstate.callbacks.get_paired_subvp_stream(state, stream); + + /* get cfg idx for associated main stream */ + cfg_idx = find_disp_cfg_idx_by_stream_id( + mapping, main_stream->stream_id); + } else { + cfg_idx = find_disp_cfg_idx_by_stream_id( + mapping, stream->stream_id); + } + + return ctx->v21.mode_programming.programming->stream_programming[cfg_idx].num_odms_required; + } + ASSERT(false); return 1; } @@ -999,14 +1036,31 @@ bool dml2_map_dc_pipes(struct dml2_context *ctx, struct dc_state *state, const s unsigned int stream_id; const unsigned int *ODMMode, *DPPPerSurface; + unsigned int odm_mode_array[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0}, dpp_per_surface_array[__DML2_WRAPPER_MAX_STREAMS_PLANES__] = {0}; struct dc_pipe_mapping_scratch scratch; if (ctx->config.map_dc_pipes_with_callbacks) return map_dc_pipes_with_callbacks( ctx, state, disp_cfg, mapping, existing_state); - ODMMode = (unsigned int *)disp_cfg->hw.ODMMode; - DPPPerSurface = disp_cfg->hw.DPPPerSurface; + if (ctx->architecture == dml2_architecture_21) { + /* + * Extract ODM and DPP outputs from DML2.1 and map them in an array as required for pipe mapping in dml2_map_dc_pipes. + * As data cannot be directly extracted in const pointers, assign these arrays to const pointers before proceeding to + * maximize the reuse of existing code. Const pointers are required because dml2.0 dml_display_cfg_st is const. + * + */ + for (i = 0; i < __DML2_WRAPPER_MAX_STREAMS_PLANES__; i++) { + odm_mode_array[i] = ctx->v21.mode_programming.programming->stream_programming[i].num_odms_required; + dpp_per_surface_array[i] = ctx->v21.mode_programming.programming->plane_programming[i].num_dpps_required; + } + + ODMMode = (const unsigned int *)odm_mode_array; + DPPPerSurface = (const unsigned int *)dpp_per_surface_array; + } else { + ODMMode = (unsigned int *)disp_cfg->hw.ODMMode; + DPPPerSurface = disp_cfg->hw.DPPPerSurface; + } for (stream_index = 0; stream_index < state->stream_count; stream_index++) { memset(&scratch, 0, sizeof(struct dc_pipe_mapping_scratch)); @@ -1025,6 +1079,22 @@ bool dml2_map_dc_pipes(struct dml2_context *ctx, struct dc_state *state, const s scratch.odm_info.odm_factor = 1; } + /* After DML2.1 update, ODM interpretation needs to change and is no longer same as for DML2.0. + * This is not an issue with new resource management logic. This block ensure backcompat + * with legacy pipe management with updated DML. + * */ + if (ctx->architecture == dml2_architecture_21) { + if (ODMMode[stream_disp_cfg_index] == 1) { + scratch.odm_info.odm_factor = 1; + } else if (ODMMode[stream_disp_cfg_index] == 2) { + scratch.odm_info.odm_factor = 2; + } else if (ODMMode[stream_disp_cfg_index] == 4) { + scratch.odm_info.odm_factor = 4; + } else { + ASSERT(false); + scratch.odm_info.odm_factor = 1; + } + } calculate_odm_slices(state->streams[stream_index], scratch.odm_info.odm_factor, scratch.odm_info.odm_slice_end_x); // If there are no planes, you still want to setup ODM... diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h index 9dab4e43c511..b566f53608c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_internal_types.h @@ -32,6 +32,8 @@ #include "dml2_wrapper.h" #include "dml2_policy.h" +#include "dml_top.h" +#include "dml21_wrapper.h" struct dml2_wrapper_optimize_configuration_params { struct display_mode_lib_st *dml_core_ctx; @@ -107,6 +109,16 @@ struct dml2_helper_det_policy_scratch { enum dml2_architecture { dml2_architecture_20, + dml2_architecture_21 +}; + +struct prepare_mcache_programming_locals { + struct dml2_build_mcache_programming_in_out build_mcache_programming_params; +}; + +struct dml21_wrapper_scratch { + struct prepare_mcache_programming_locals prepare_mcache_locals; + struct pipe_ctx temp_pipe; }; struct dml2_pipe_combine_factor { @@ -130,6 +142,14 @@ struct dml2_context { struct dml2_wrapper_scratch scratch; struct dcn_watermarks g6_temp_read_watermark_set; } v20; + struct { + struct dml21_wrapper_scratch scratch; + struct dml2_initialize_instance_in_out dml_init; + struct dml2_display_cfg display_config; + struct dml2_check_mode_supported_in_out mode_support; + struct dml2_build_mode_programming_in_out mode_programming; + struct dml2_dml_to_dc_pipe_mapping dml_to_dc_pipe_mapping; + } v21; }; }; diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c index a41812598ce8..150872d6409f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c @@ -34,7 +34,6 @@ void dml2_init_ip_params(struct dml2_context *dml2, const struct dc *in_dc, struct ip_params_st *out) { switch (dml2->v20.dml_core_ctx.project) { - case dml_project_dcn32: case dml_project_dcn321: default: @@ -176,6 +175,69 @@ void dml2_init_ip_params(struct dml2_context *dml2, const struct dc *in_dc, stru out->config_return_buffer_segment_size_in_kbytes = 64; /*required, but not exist,, hard coded in dml2_translate_ip_params*/ break; + case dml_project_dcn401: + // Hardcoded values for DCN4m + out->vblank_nom_default_us = 668; //600; + out->rob_buffer_size_kbytes = 192; //128; + out->config_return_buffer_size_in_kbytes = 1344; //1280; + out->config_return_buffer_segment_size_in_kbytes = 64; + out->compressed_buffer_segment_size_in_kbytes = 64; + out->meta_fifo_size_in_kentries = 22; + out->dpte_buffer_size_in_pte_reqs_luma = 68; + out->dpte_buffer_size_in_pte_reqs_chroma = 36; + out->gpuvm_max_page_table_levels = 4; + out->pixel_chunk_size_kbytes = 8; + out->alpha_pixel_chunk_size_kbytes = 4; + out->min_pixel_chunk_size_bytes = 1024; + out->writeback_chunk_size_kbytes = 8; + out->line_buffer_size_bits = 1171920; + out->max_line_buffer_lines = 32; + out->writeback_interface_buffer_size_kbytes = 90; + //Number of pipes after DCN Pipe harvesting + out->max_num_dpp = dml2->config.dcn_pipe_count; + out->max_num_otg = dml2->config.dcn_pipe_count; + out->max_num_wb = 1; + out->max_dchub_pscl_bw_pix_per_clk = 4; + out->max_pscl_lb_bw_pix_per_clk = 2; + out->max_lb_vscl_bw_pix_per_clk = 4; + out->max_vscl_hscl_bw_pix_per_clk = 4; + out->max_hscl_ratio = 6; + out->max_vscl_ratio = 6; + out->max_hscl_taps = 8; + out->max_vscl_taps = 8; + out->dispclk_ramp_margin_percent = 1; + out->dppclk_delay_subtotal = 47; + out->dppclk_delay_scl = 50; + out->dppclk_delay_scl_lb_only = 16; + out->dppclk_delay_cnvc_formatter = 28; + out->dppclk_delay_cnvc_cursor = 6; + out->dispclk_delay_subtotal = 125; + out->cursor_buffer_size = 24; //16 + out->cursor_chunk_size = 2; + out->max_inter_dcn_tile_repeaters = 8; + out->writeback_max_hscl_ratio = 1; + out->writeback_max_vscl_ratio = 1; + out->writeback_min_hscl_ratio = 1; + out->writeback_min_vscl_ratio = 1; + out->writeback_max_hscl_taps = 1; + out->writeback_max_vscl_taps = 1; + out->writeback_line_buffer_buffer_size = 0; + out->num_dsc = 4; + out->maximum_dsc_bits_per_component = 12; + out->maximum_pixels_per_line_per_dsc_unit = 5760; + out->dsc422_native_support = true; + out->dcc_supported = true; + out->ptoi_supported = false; + + out->gpuvm_enable = false; + out->hostvm_enable = false; + out->cursor_64bpp_support = true; //false; + out->dynamic_metadata_vm_enabled = false; + + out->max_num_hdmi_frl_outputs = 1; + out->max_num_dp2p0_outputs = 4; //2; + out->max_num_dp2p0_streams = 4; + break; } } @@ -236,6 +298,20 @@ void dml2_init_socbb_params(struct dml2_context *dml2, const struct dc *in_dc, s out->dispclk_dppclk_vco_speed_mhz = 3600; break; + case dml_project_dcn401: + out->pct_ideal_fabric_bw_after_urgent = 76; //67; + out->max_avg_sdp_bw_use_normal_percent = 75; //80; + out->max_avg_fabric_bw_use_normal_percent = 57; //60; + + out->urgent_out_of_order_return_per_channel_pixel_only_bytes = 0; //4096; + out->urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 0; //4096; + out->urgent_out_of_order_return_per_channel_vm_only_bytes = 0; //4096; + + out->num_chans = 16; + out->round_trip_ping_latency_dcfclk_cycles = 1000; //263; + out->smn_latency_us = 0; //2 us + out->mall_allocated_for_dcn_mbytes = dml2->config.mall_cfg.max_cab_allocation_bytes / 1048576; // 64; + break; } /* ---Overrides if available--- */ if (dml2->config.bbox_overrides.dram_num_chan) @@ -345,6 +421,41 @@ void dml2_init_soc_states(struct dml2_context *dml2, const struct dc *in_dc, p->in_states->state_array[1].dcfclk_mhz = 1434.0; p->in_states->state_array[1].dram_speed_mts = 1000 * transactions_per_mem_clock; break; + case dml_project_dcn401: + p->in_states->num_states = 2; + transactions_per_mem_clock = 16; + p->in_states->state_array[0].socclk_mhz = 300; //620.0; + p->in_states->state_array[0].dscclk_mhz = 666.667; //716.667; + p->in_states->state_array[0].phyclk_mhz = 810; + p->in_states->state_array[0].phyclk_d18_mhz = 667; + p->in_states->state_array[0].phyclk_d32_mhz = 625; + p->in_states->state_array[0].dtbclk_mhz = 2000; //1564.0; + p->in_states->state_array[0].fabricclk_mhz = 300; //450.0; + p->in_states->state_array[0].dcfclk_mhz = 200; //300.0; + p->in_states->state_array[0].dispclk_mhz = 2000; //2150.0; + p->in_states->state_array[0].dppclk_mhz = 2000; //2150.0; + p->in_states->state_array[0].dram_speed_mts = 97 * transactions_per_mem_clock; //100 * + + p->in_states->state_array[0].urgent_latency_pixel_data_only_us = 4; + p->in_states->state_array[0].urgent_latency_pixel_mixed_with_vm_data_us = 0; + p->in_states->state_array[0].urgent_latency_vm_data_only_us = 0; + p->in_states->state_array[0].writeback_latency_us = 12; + p->in_states->state_array[0].urgent_latency_adjustment_fabric_clock_component_us = 1; + p->in_states->state_array[0].urgent_latency_adjustment_fabric_clock_reference_mhz = 1000; //3000; + p->in_states->state_array[0].sr_exit_z8_time_us = 0; + p->in_states->state_array[0].sr_enter_plus_exit_z8_time_us = 0; + p->in_states->state_array[0].dram_clock_change_latency_us = 400; + p->in_states->state_array[0].use_ideal_dram_bw_strobe = true; + p->in_states->state_array[0].sr_exit_time_us = 15.70; //42.97; + p->in_states->state_array[0].sr_enter_plus_exit_time_us = 20.20; //49.94; + p->in_states->state_array[0].fclk_change_latency_us = 0; //20; + p->in_states->state_array[0].usr_retraining_latency_us = 0; //2; + + p->in_states->state_array[1].socclk_mhz = 1600; //1200.0; + p->in_states->state_array[1].fabricclk_mhz = 2500; //2500.0; + p->in_states->state_array[1].dcfclk_mhz = 1800; //1564.0; + p->in_states->state_array[1].dram_speed_mts = 1125 * transactions_per_mem_clock; + break; } /* Override from passed values, if available */ @@ -771,6 +882,19 @@ static void populate_dml_surface_cfg_from_plane_state(enum dml_project_id dml2_p default: out->SurfaceTiling[location] = (enum dml_swizzle_mode)in->tiling_info.gfx9.swizzle; break; + case dml_project_dcn401: + // Temporary use gfx11 swizzle in dml, until proper dml for DCN4x is integrated/implemented + switch (in->tiling_info.gfx_addr3.swizzle) { + case DC_ADDR3_SW_4KB_2D: + case DC_ADDR3_SW_64KB_2D: + case DC_ADDR3_SW_256KB_2D: + default: + out->SurfaceTiling[location] = dml_sw_64kb_r_x; + break; + case DC_ADDR3_SW_LINEAR: + out->SurfaceTiling[location] = dml_sw_linear; + break; + } } switch (in->format) { diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c index 9412d5384a41..4be304ebf0b4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c @@ -31,6 +31,7 @@ #include "dml2_translation_helper.h" #include "dml2_mall_phantom.h" #include "dml2_dc_resource_mgmt.h" +#include "dml21_wrapper.h" static void initialize_dml2_ip_params(struct dml2_context *dml2, const struct dc *in_dc, struct ip_params_st *out) @@ -699,6 +700,11 @@ bool dml2_validate(const struct dc *in_dc, struct dc_state *context, struct dml2 return false; dml2_apply_debug_options(in_dc, dml2); + /* DML2.1 validation path */ + if (dml2->architecture == dml2_architecture_21) { + out = dml21_validate(in_dc, context, dml2, fast_validate); + return out; + } /* Use dml_validate_only for fast_validate path */ if (fast_validate) @@ -715,6 +721,10 @@ static inline struct dml2_context *dml2_allocate_memory(void) static void dml2_init(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 || in_dc->ctx->dce_version == DCN_VERSION_3_2)) { + dml21_reinit(in_dc, dml2, config); + } // Store config options (*dml2)->config = *config; @@ -732,6 +742,9 @@ static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_op case DCN_VERSION_3_21: (*dml2)->v20.dml_core_ctx.project = dml_project_dcn321; break; + case DCN_VERSION_4_01: + (*dml2)->v20.dml_core_ctx.project = dml_project_dcn401; + break; default: (*dml2)->v20.dml_core_ctx.project = dml_project_default; break; @@ -746,6 +759,12 @@ static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_op bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2) { + DC_FP_START(); + // 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 || in_dc->ctx->dce_version == DCN_VERSION_3_2)) { + return dml21_create(in_dc, dml2, config); + } + // Allocate Mode Lib Ctx *dml2 = dml2_allocate_memory(); @@ -754,6 +773,7 @@ bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options dml2_init(in_dc, config, dml2); + DC_FP_END(); return true; } @@ -775,6 +795,10 @@ void dml2_extract_dram_and_fclk_change_support(struct dml2_context *dml2, void dml2_copy(struct dml2_context *dst_dml2, struct dml2_context *src_dml2) { + if (src_dml2->architecture == dml2_architecture_21) { + dml21_copy(dst_dml2, src_dml2); + return; + } /* copy Mode Lib Ctx */ memcpy(dst_dml2, src_dml2, sizeof(struct dml2_context)); } @@ -782,6 +806,8 @@ void dml2_copy(struct dml2_context *dst_dml2, bool dml2_create_copy(struct dml2_context **dst_dml2, struct dml2_context *src_dml2) { + if (src_dml2->architecture == dml2_architecture_21) + return dml21_create_copy(dst_dml2, src_dml2); /* Allocate Mode Lib Ctx */ *dst_dml2 = dml2_allocate_memory(); @@ -798,6 +824,10 @@ void dml2_reinit(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 || in_dc->ctx->dce_version == DCN_VERSION_3_2)) { + dml21_reinit(in_dc, dml2, config); + } dml2_init(in_dc, config, dml2); } diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h index 4a8bd2f4195e..97e013ce5516 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h @@ -192,6 +192,14 @@ struct dml2_soc_bbox_overrides { struct dml2_clks_limit_table clks_table; }; +enum dml2_force_pstate_methods { + dml2_force_pstate_method_auto = 0, + dml2_force_pstate_method_vactive, + dml2_force_pstate_method_vblank, + dml2_force_pstate_method_drr, + dml2_force_pstate_method_subvp, +}; + struct dml2_configuration_options { int dcn_pipe_count; bool use_native_pstate_optimization; @@ -215,6 +223,12 @@ struct dml2_configuration_options { struct dml2_soc_bbox_overrides bbox_overrides; unsigned int max_segments_per_hubp; unsigned int det_segment_size; + /* Only for debugging purposes when initializing SOCBB params via tool for DML21. */ + struct socbb_ip_params_external *external_socbb_ip_params; + struct { + bool force_pstate_method_enable; + enum dml2_force_pstate_methods force_pstate_method_value; + } pmo; bool map_dc_pipes_with_callbacks; bool use_clock_dc_limits; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/Makefile b/drivers/gpu/drm/amd/display/dc/dpp/Makefile index 99bd36073561..8324a56fe7db 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dpp/Makefile @@ -74,4 +74,10 @@ AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN35) ############################################################################### -endif \ No newline at end of file +DPP_DCN401 = dcn401_dpp.o dcn401_dpp_cm.o dcn401_dpp_dscl.o + +AMD_DAL_DPP_DCN401 = $(addprefix $(AMDDALPATH)/dc/dpp/dcn401/,$(DPP_DCN401)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DPP_DCN401) + +endif 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 56ebd7164dd7..c433f4b876e9 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 @@ -432,4 +432,60 @@ bool dpp2_construct( return true; } +/*compute the maximum number of lines that we can fit in the line buffer*/ +void dscl2_spl_calc_lb_num_partitions( + bool alpha_en, + const struct spl_scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c) +{ + int memory_line_size_y, memory_line_size_c, memory_line_size_a, + lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a; + + int line_size = scl_data->viewport.width < scl_data->recout.width ? + scl_data->viewport.width : scl_data->recout.width; + int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ? + scl_data->viewport_c.width : scl_data->recout.width; + + if (line_size == 0) + line_size = 1; + + if (line_size_c == 0) + line_size_c = 1; + + memory_line_size_y = (line_size + 5) / 6; /* +5 to ceil */ + memory_line_size_c = (line_size_c + 5) / 6; /* +5 to ceil */ + memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */ + + if (lb_config == LB_MEMORY_CONFIG_1) { + lb_memory_size = 970; + lb_memory_size_c = 970; + lb_memory_size_a = 970; + } else if (lb_config == LB_MEMORY_CONFIG_2) { + lb_memory_size = 1290; + lb_memory_size_c = 1290; + lb_memory_size_a = 1290; + } else if (lb_config == LB_MEMORY_CONFIG_3) { + /* 420 mode: using 3rd mem from Y, Cr and Cb */ + lb_memory_size = 970 + 1290 + 484 + 484 + 484; + lb_memory_size_c = 970 + 1290; + lb_memory_size_a = 970 + 1290 + 484; + } else { + lb_memory_size = 970 + 1290 + 484; + lb_memory_size_c = 970 + 1290 + 484; + lb_memory_size_a = 970 + 1290 + 484; + } + *num_part_y = lb_memory_size / memory_line_size_y; + *num_part_c = lb_memory_size_c / memory_line_size_c; + num_partitions_a = lb_memory_size_a / memory_line_size_a; + if (alpha_en + && (num_partitions_a < *num_part_y)) + *num_part_y = num_partitions_a; + + if (*num_part_y > 64) + *num_part_y = 64; + if (*num_part_c > 64) + *num_part_c = 64; +} diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.h index 49cb25c9cb36..cd1706d301e7 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.h @@ -26,7 +26,7 @@ #define __DCN20_DPP_H__ #include "dcn10/dcn10_dpp.h" - +#include "spl/dc_spl_types.h" #define TO_DCN20_DPP(dpp)\ container_of(dpp, struct dcn20_dpp, base) @@ -748,6 +748,13 @@ void dscl2_calc_lb_num_partitions( int *num_part_y, int *num_part_c); +void dscl2_spl_calc_lb_num_partitions( + bool alpha_en, + const struct spl_scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c); + void dpp2_set_cursor_attributes( struct dpp *dpp_base, struct dc_cursor_attributes *cursor_attributes); diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.h index 269f437c1633..b110f35ef66b 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.h @@ -175,8 +175,6 @@ SRI(CM_BLNDGAM_RAMB_START_SLOPE_CNTL_R, CM, id),\ SRI(CM_BLNDGAM_LUT_CONTROL, CM, id) - - #define DPP_REG_LIST_SH_MASK_DCN30_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),\ @@ -600,7 +598,7 @@ bool dpp3_get_optimal_number_of_taps( struct scaler_data *scl_data, const struct scaling_taps *in_taps); -void dpp3_cnv_setup ( +void dpp3_cnv_setup( struct dpp *dpp_base, enum surface_pixel_format format, enum expansion_mode mode, diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.c index 41679997b44d..fa67e54bf94e 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.c @@ -163,3 +163,76 @@ bool dpp32_construct( return true; } +void dscl32_spl_calc_lb_num_partitions( + bool alpha_en, + const struct spl_scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c) +{ + int memory_line_size_y, memory_line_size_c, memory_line_size_a, + lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a; + + int line_size = scl_data->viewport.width < scl_data->recout.width ? + scl_data->viewport.width : scl_data->recout.width; + int line_size_c = scl_data->viewport_c.width < scl_data->recout.width ? + scl_data->viewport_c.width : scl_data->recout.width; + + if (line_size == 0) + line_size = 1; + + if (line_size_c == 0) + line_size_c = 1; + + memory_line_size_y = (line_size + 5) / 6; /* +5 to ceil */ + memory_line_size_c = (line_size_c + 5) / 6; /* +5 to ceil */ + memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */ + + if (lb_config == LB_MEMORY_CONFIG_1) { + lb_memory_size = 970; + lb_memory_size_c = 970; + lb_memory_size_a = 970; + } else if (lb_config == LB_MEMORY_CONFIG_2) { + lb_memory_size = 1290; + lb_memory_size_c = 1290; + lb_memory_size_a = 1290; + } else if (lb_config == LB_MEMORY_CONFIG_3) { + if (scl_data->viewport.width == scl_data->h_active && + scl_data->viewport.height == scl_data->v_active) { + /* 420 mode: luma using all 3 mem from Y, plus 3rd mem from Cr and Cb */ + /* use increased LB size for calculation only if Scaler not enabled */ + lb_memory_size = 970 + 1290 + 1170 + 1170 + 1170; + lb_memory_size_c = 970 + 1290; + lb_memory_size_a = 970 + 1290 + 1170; + } else { + /* 420 mode: luma using all 3 mem from Y, plus 3rd mem from Cr and Cb */ + lb_memory_size = 970 + 1290 + 484 + 484 + 484; + lb_memory_size_c = 970 + 1290; + lb_memory_size_a = 970 + 1290 + 484; + } + } else { + if (scl_data->viewport.width == scl_data->h_active && + scl_data->viewport.height == scl_data->v_active) { + /* use increased LB size for calculation only if Scaler not enabled */ + lb_memory_size = 970 + 1290 + 1170; + lb_memory_size_c = 970 + 1290 + 1170; + lb_memory_size_a = 970 + 1290 + 1170; + } else { + lb_memory_size = 970 + 1290 + 484; + lb_memory_size_c = 970 + 1290 + 484; + lb_memory_size_a = 970 + 1290 + 484; + } + } + *num_part_y = lb_memory_size / memory_line_size_y; + *num_part_c = lb_memory_size_c / memory_line_size_c; + num_partitions_a = lb_memory_size_a / memory_line_size_a; + + if (alpha_en + && (num_partitions_a < *num_part_y)) + *num_part_y = num_partitions_a; + + if (*num_part_y > 32) + *num_part_y = 32; + if (*num_part_c > 32) + *num_part_c = 32; +} diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.h index 572958d287eb..992df172378c 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn32/dcn32_dpp.h @@ -27,6 +27,7 @@ #include "dcn20/dcn20_dpp.h" #include "dcn30/dcn30_dpp.h" +#include "spl/dc_spl_types.h" bool dpp32_construct(struct dcn3_dpp *dpp3, struct dc_context *ctx, @@ -35,4 +36,11 @@ bool dpp32_construct(struct dcn3_dpp *dpp3, const struct dcn3_dpp_shift *tf_shift, const struct dcn3_dpp_mask *tf_mask); +void dscl32_spl_calc_lb_num_partitions( + bool alpha_en, + const struct spl_scaler_data *scl_data, + enum lb_memory_config lb_config, + int *num_part_y, + int *num_part_c); + #endif /* __DCN32_DPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dsc/Makefile b/drivers/gpu/drm/amd/display/dc/dsc/Makefile index b183ba5a692e..026af72ca2c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dsc/Makefile @@ -22,9 +22,14 @@ DSC_DCN35 = dcn35_dsc.o AMD_DISPLAY_FILES += $(addprefix $(AMDDALPATH)/dc/dsc/dcn35/,$(DSC_DCN35)) +############################################################################### +# DCN401 +############################################################################### +DSC_DCN401 += dcn401_dsc.o + +AMD_DISPLAY_FILES += $(addprefix $(AMDDALPATH)/dc/dsc/dcn401/,$(DSC_DCN401)) -endif DSC = dc_dsc.o rc_calc.o rc_calc_dpi.o @@ -32,3 +37,4 @@ AMD_DAL_DSC = $(addprefix $(AMDDALPATH)/dc/dsc/,$(DSC)) AMD_DISPLAY_FILES += $(AMD_DAL_DSC) +endif diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index 150ef23440a2..80ed905ebfe6 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -49,103 +49,6 @@ static bool disable_128b_132b_stream_overhead; #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) #endif -/* Need to account for padding due to pixel-to-symbol packing - * for uncompressed 128b/132b streams. - */ -static uint32_t apply_128b_132b_stream_overhead( - const struct dc_crtc_timing *timing, const uint32_t kbps) -{ - uint32_t total_kbps = kbps; - - if (disable_128b_132b_stream_overhead) - return kbps; - - if (!timing->flags.DSC) { - struct fixed31_32 bpp; - struct fixed31_32 overhead_factor; - - bpp = dc_fixpt_from_int(kbps); - bpp = dc_fixpt_div_int(bpp, timing->pix_clk_100hz / 10); - - /* Symbols_per_HActive = HActive * bpp / (4 lanes * 32-bit symbol size) - * Overhead_factor = ceil(Symbols_per_HActive) / Symbols_per_HActive - */ - overhead_factor = dc_fixpt_from_int(timing->h_addressable); - overhead_factor = dc_fixpt_mul(overhead_factor, bpp); - overhead_factor = dc_fixpt_div_int(overhead_factor, 128); - overhead_factor = dc_fixpt_div( - dc_fixpt_from_int(dc_fixpt_ceil(overhead_factor)), - overhead_factor); - - total_kbps = dc_fixpt_ceil( - dc_fixpt_mul_int(overhead_factor, total_kbps)); - } - - return total_kbps; -} - -uint32_t dc_bandwidth_in_kbps_from_timing( - const struct dc_crtc_timing *timing, - const enum dc_link_encoding_format link_encoding) -{ - uint32_t bits_per_channel = 0; - uint32_t kbps; - - if (timing->flags.DSC) - return dc_dsc_stream_bandwidth_in_kbps(timing, - timing->dsc_cfg.bits_per_pixel, - timing->dsc_cfg.num_slices_h, - timing->dsc_cfg.is_dp); - - switch (timing->display_color_depth) { - case COLOR_DEPTH_666: - bits_per_channel = 6; - break; - case COLOR_DEPTH_888: - bits_per_channel = 8; - break; - case COLOR_DEPTH_101010: - bits_per_channel = 10; - break; - case COLOR_DEPTH_121212: - bits_per_channel = 12; - break; - case COLOR_DEPTH_141414: - bits_per_channel = 14; - break; - case COLOR_DEPTH_161616: - bits_per_channel = 16; - break; - default: - ASSERT(bits_per_channel != 0); - bits_per_channel = 8; - break; - } - - kbps = timing->pix_clk_100hz / 10; - kbps *= bits_per_channel; - - if (timing->flags.Y_ONLY != 1) { - /*Only YOnly make reduce bandwidth by 1/3 compares to RGB*/ - kbps *= 3; - if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) - kbps /= 2; - else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) - kbps = kbps * 2 / 3; - } - - if (link_encoding == DC_LINK_ENCODING_DP_128b_132b) - kbps = apply_128b_132b_stream_overhead(timing, kbps); - - if (link_encoding == DC_LINK_ENCODING_HDMI_FRL && - timing->vic == 0 && timing->hdmi_vic == 0 && - timing->frl_uncompressed_video_bandwidth_in_kbps != 0) - kbps = timing->frl_uncompressed_video_bandwidth_in_kbps; - - return kbps; -} - - /* Forward Declerations */ static bool decide_dsc_bandwidth_range( const uint32_t min_bpp_x16, @@ -1246,6 +1149,11 @@ void dc_set_disable_128b_132b_stream_overhead(bool disable) disable_128b_132b_stream_overhead = disable; } +bool dc_get_disable_128b_132b_stream_overhead(void) +{ + return disable_128b_132b_stream_overhead; +} + void dc_dsc_get_default_config_option(const struct dc *dc, struct dc_dsc_config_options *options) { options->dsc_min_slice_height_override = dc->debug.dsc_min_slice_height_override; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/Makefile b/drivers/gpu/drm/amd/display/dc/gpio/Makefile index bc47481a158e..b72e2a9f9a28 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/Makefile +++ b/drivers/gpu/drm/amd/display/dc/gpio/Makefile @@ -122,3 +122,13 @@ GPIO_DCN32 = hw_translate_dcn32.o hw_factory_dcn32.o AMD_DAL_GPIO_DCN32 = $(addprefix $(AMDDALPATH)/dc/gpio/dcn32/,$(GPIO_DCN32)) AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCN32) + +############################################################################### +# DCN 4.01 +############################################################################### +GPIO_DCN401 = hw_translate_dcn401.o hw_factory_dcn401.o + +AMD_DAL_GPIO_DCN401 = $(addprefix $(AMDDALPATH)/dc/gpio/dcn401/,$(GPIO_DCN401)) + +AMD_DISPLAY_FILES += $(AMD_DAL_GPIO_DCN401) + 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 8f1a95b77830..9a0952f9004f 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_factory.c @@ -52,6 +52,7 @@ #include "dcn30/hw_factory_dcn30.h" #include "dcn315/hw_factory_dcn315.h" #include "dcn32/hw_factory_dcn32.h" +#include "dcn401/hw_factory_dcn401.h" bool dal_hw_factory_init( struct hw_factory *factory, @@ -113,6 +114,9 @@ bool dal_hw_factory_init( case DCN_VERSION_3_51: dal_hw_factory_dcn32_init(factory); return true; + case DCN_VERSION_4_01: + dal_hw_factory_dcn401_init(factory); + return true; default: ASSERT_CRITICAL(false); return false; diff --git a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c index 37166b2b3fee..9832247ee739 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/hw_translate.c @@ -52,6 +52,7 @@ #include "dcn30/hw_translate_dcn30.h" #include "dcn315/hw_translate_dcn315.h" #include "dcn32/hw_translate_dcn32.h" +#include "dcn401/hw_translate_dcn401.h" /* * This unit @@ -114,6 +115,9 @@ bool dal_hw_translate_init( case DCN_VERSION_3_51: dal_hw_translate_dcn32_init(translate); return true; + case DCN_VERSION_4_01: + dal_hw_translate_dcn401_init(translate); + return true; default: BREAK_TO_DEBUGGER(); return false; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/Makefile b/drivers/gpu/drm/amd/display/dc/hwss/Makefile index cf8aa23b4415..ba55050be161 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/Makefile +++ b/drivers/gpu/drm/amd/display/dc/hwss/Makefile @@ -190,4 +190,9 @@ AMD_DISPLAY_FILES += $(AMD_DAL_HWSS_DCN351) ############################################################################### +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) endif 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 0c4aef8ffe2c..55fb69fb7777 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 @@ -233,7 +233,8 @@ static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx) " rc_pg_flc rc_mc_fll rc_mc_flc pr_nom_l pr_nom_c rc_pg_nl rc_pg_nc " " mr_nom_l mr_nom_c rc_mc_nl rc_mc_nc rc_ld_pl rc_ld_pc rc_ld_l " " rc_ld_c cha_cur0 ofst_cur1 cha_cur1 vr_af_vc0 ddrq_limt x_rt_dlay" - " x_rp_dlay x_rr_sfl\n"); + " x_rp_dlay x_rr_sfl rc_td_grp\n"); + for (i = 0; i < pool->pipe_count; i++) { struct dcn_hubp_state *s = &(TO_DCN10_HUBP(pool->hubps[i])->state); struct _vcs_dpi_display_dlg_regs_st *dlg_regs = &s->dlg_attr; @@ -241,7 +242,7 @@ static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx) if (!s->blank_en) DTN_INFO("[%2d]: %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh" " %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh" - " %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh\n", + " %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %8xh %xh\n", pool->hubps[i]->inst, dlg_regs->refcyc_h_blank_end, dlg_regs->dlg_vblank_end, dlg_regs->min_dst_y_next_start, dlg_regs->refcyc_per_htotal, dlg_regs->refcyc_x_after_scaler, dlg_regs->dst_y_after_scaler, dlg_regs->dst_y_prefetch, dlg_regs->dst_y_per_vm_vblank, dlg_regs->dst_y_per_row_vblank, @@ -259,7 +260,7 @@ static void dcn10_log_hubp_states(struct dc *dc, void *log_ctx) dlg_regs->refcyc_per_line_delivery_c, dlg_regs->chunk_hdl_adjust_cur0, dlg_regs->dst_y_offset_cur1, dlg_regs->chunk_hdl_adjust_cur1, dlg_regs->vready_after_vcount0, dlg_regs->dst_y_delta_drq_limit, dlg_regs->xfc_reg_transfer_delay, dlg_regs->xfc_reg_precharge_delay, - dlg_regs->xfc_reg_remote_surface_flip_latency); + dlg_regs->xfc_reg_remote_surface_flip_latency, dlg_regs->refcyc_per_tdlut_group); } DTN_INFO("========TTU========\n"); 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 7d833fa6dd77..651162a5043c 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 @@ -204,7 +204,7 @@ static int find_free_gsl_group(const struct dc *dc) * gsl_0 <=> pipe_ctx->stream_res.gsl_group == 1 * Using a magic value like -1 would require tracking all inits/resets */ - void dcn20_setup_gsl_group_as_lock( +void dcn20_setup_gsl_group_as_lock( const struct dc *dc, struct pipe_ctx *pipe_ctx, bool enable) @@ -1709,6 +1709,11 @@ static void dcn20_update_dchubp_dpp( plane_state->color_space, NULL); + if (dpp->funcs->set_cursor_matrix) { + dpp->funcs->set_cursor_matrix(dpp, + plane_state->color_space, + plane_state->cursor_csc_color_matrix); + } if (dpp->funcs->dpp_program_bias_and_scale) { //TODO :for CNVC set scale and bias registers if necessary build_prescale_params(&bns_params, plane_state); @@ -1908,6 +1913,10 @@ static void dcn20_program_pipe( if (dc->res_pool->hubbub->funcs->program_det_size) dc->res_pool->hubbub->funcs->program_det_size( dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->det_buffer_size_kb); + + if (dc->res_pool->hubbub->funcs->program_det_segments) + dc->res_pool->hubbub->funcs->program_det_segments( + dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->hubp_regs.det_size); } if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw) @@ -1917,6 +1926,11 @@ static void dcn20_program_pipe( || pipe_ctx->plane_state->update_flags.bits.hdr_mult) hws->funcs.set_hdr_multiplier(pipe_ctx); + if (hws->funcs.populate_mcm_luts) { + hws->funcs.populate_mcm_luts(dc, pipe_ctx, pipe_ctx->plane_state->mcm_luts, + pipe_ctx->plane_state->lut_bank_a); + pipe_ctx->plane_state->lut_bank_a = !pipe_ctx->plane_state->lut_bank_a; + } if (pipe_ctx->update_flags.bits.enable || pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change || pipe_ctx->plane_state->update_flags.bits.gamma_change || @@ -2073,6 +2087,8 @@ void dcn20_program_front_end_for_ctx( (context->res_ctx.pipe_ctx[i].plane_state && dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM))) { if (hubbub->funcs->program_det_size) hubbub->funcs->program_det_size(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0); + if (dc->res_pool->hubbub->funcs->program_det_segments) + dc->res_pool->hubbub->funcs->program_det_segments(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0); } hws->funcs.plane_atomic_disconnect(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]); DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c index 67d661dbd5b7..b1f79ca7d77a 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c @@ -30,6 +30,7 @@ #include "dcn30/dcn30_hwseq.h" #include "dcn31/dcn31_hwseq.h" #include "dcn32/dcn32_hwseq.h" +#include "dcn401/dcn401_hwseq.h" #include "dcn32_init.h" static const struct hw_sequencer_funcs dcn32_funcs = { @@ -162,6 +163,7 @@ static const struct hwseq_private_funcs dcn32_private_funcs = { .is_dp_dig_pixel_rate_div_policy = dcn32_is_dp_dig_pixel_rate_div_policy, .apply_single_controller_ctx_to_hw = dce110_apply_single_controller_ctx_to_hw, .reset_back_end_for_pipe = dcn20_reset_back_end_for_pipe, + .populate_mcm_luts = dcn401_populate_mcm_luts, }; void dcn32_hw_sequencer_init_functions(struct dc *dc) 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 7c339e7e7117..d2d1ba30f6ae 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h @@ -141,6 +141,12 @@ struct subvp_save_surf_addr { uint8_t subvp_index; }; +struct fams2_global_control_lock_fast_params { + struct dc *dc; + bool is_required; + bool lock; +}; + union block_sequence_params { struct update_plane_addr_params update_plane_addr_params; struct subvp_pipe_control_lock_fast_params subvp_pipe_control_lock_fast_params; @@ -159,6 +165,7 @@ union block_sequence_params { struct set_output_csc_params set_output_csc_params; struct set_ocsc_default_params set_ocsc_default_params; struct subvp_save_surf_addr subvp_save_surf_addr; + struct fams2_global_control_lock_fast_params fams2_global_control_lock_fast_params; }; enum block_sequence_func { @@ -179,6 +186,8 @@ enum block_sequence_func { MPC_SET_OUTPUT_CSC, MPC_SET_OCSC_DEFAULT, DMUB_SUBVP_SAVE_SURF_ADDR, + DMUB_FAMS2_GLOBAL_CONTROL_LOCK_FAST, + }; struct block_sequence { @@ -430,6 +439,13 @@ struct hw_sequencer_funcs { bool (*is_pipe_topology_transition_seamless)(struct dc *dc, const struct dc_state *cur_ctx, const struct dc_state *new_ctx); + void (*fams2_global_control_lock)(struct dc *dc, + struct dc_state *context, + bool lock); + void (*fams2_update_config)(struct dc *dc, + struct dc_state *context, + bool enable); + void (*fams2_global_control_lock_fast)(union block_sequence_params *params); void (*set_long_vtotal)(struct pipe_ctx **pipe_ctx, int num_pipes, uint32_t v_total_min, uint32_t v_total_max); }; @@ -463,6 +479,12 @@ void get_subvp_visual_confirm_color( struct pipe_ctx *pipe_ctx, struct tg_color *color); +void get_fams2_visual_confirm_color( + struct dc *dc, + struct dc_state *context, + struct pipe_ctx *pipe_ctx, + struct tg_color *color); + void get_mclk_switch_visual_confirm_color( struct pipe_ctx *pipe_ctx, struct tg_color *color); 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 341219cf4144..3a23d05a615e 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 @@ -176,6 +176,10 @@ struct hwseq_private_funcs { void (*reset_back_end_for_pipe)(struct dc *dc, struct pipe_ctx *pipe_ctx, struct dc_state *context); + void (*populate_mcm_luts)(struct dc *dc, + struct pipe_ctx *pipe_ctx, + struct dc_cm2_func_luts mcm_luts, + bool lut_bank_a); }; 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 028b2f971e36..286f3219b77e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h +++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h @@ -39,6 +39,7 @@ #include "panel_cntl.h" #include "dmub/inc/dmub_cmd.h" #include "pg_cntl.h" +#include "spl/dc_spl.h" #define MAX_CLOCK_SOURCES 7 #define MAX_SVP_PHANTOM_STREAMS 2 @@ -60,6 +61,9 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state, #include "transform.h" #include "dpp.h" +#include "dml2/dml21/inc/dml_top_dchub_registers.h" +#include "dml2/dml21/inc/dml_top_types.h" + struct resource_pool; struct dc_state; struct resource_context; @@ -159,6 +163,7 @@ struct resource_funcs { struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *stream); + enum dc_status (*patch_unknown_plane_state)( struct dc_plane_state *plane_state); @@ -166,6 +171,7 @@ struct resource_funcs { struct resource_context *res_ctx, const struct resource_pool *pool, struct dc_stream_state *stream); + void (*populate_dml_writeback_from_context)( struct dc *dc, struct resource_context *res_ctx, @@ -176,6 +182,7 @@ struct resource_funcs { struct dc_state *context, display_e2e_pipe_params_st *pipes, int pipe_cnt); + void (*update_bw_bounding_box)( struct dc *dc, struct clk_bw_params *bw_params); @@ -292,7 +299,6 @@ struct resource_pool { struct abm *abm; struct dmcu *dmcu; struct dmub_psr *psr; - struct dmub_replay *replay; struct abm *multiple_abms[MAX_PIPES]; @@ -342,6 +348,13 @@ struct plane_resource { /* scl_data is scratch space required to program a plane */ struct scaler_data scl_data; /* Below pointers to hw objects are required to enable the plane */ + /* spl_in and spl_out are the input and output structures for SPL + * which are required when using Scaler Programming Library + * these are scratch spaces needed when programming a plane + */ + struct spl_in spl_in; + struct spl_out spl_out; + /* Below pointers to hw objects are required to enable the plane */ struct hubp *hubp; struct mem_input *mi; struct input_pixel_processor *ipp; @@ -440,6 +453,8 @@ struct pipe_ctx { int det_buffer_size_kb; bool unbounded_req; unsigned int surface_size_in_mall_bytes; + struct dml2_dchub_per_pipe_register_set hubp_regs; + struct dml2_hubp_pipe_mcache_regs mcache_regs; struct dwbc *dwbc; struct mcif_wb *mcif_wb; @@ -509,6 +524,10 @@ struct dcn_bw_output { unsigned int mall_subvp_size_bytes; unsigned int legacy_svp_drr_stream_index; bool legacy_svp_drr_stream_index_valid; + struct dml2_mcache_surface_allocation mcache_allocations[DML2_MAX_PLANES]; + struct dmub_fams2_stream_static_state fams2_stream_params[DML2_MAX_PLANES]; + unsigned fams2_stream_count; + struct dml2_display_arb_regs arb_regs; }; union bw_output { 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 4f7480f60c85..d5fefce3e74b 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 @@ -39,6 +39,8 @@ #define WM_C 2 #define WM_D 3 #define WM_SET_COUNT 4 +#define WM_1A 2 +#define WM_1B 3 #define DCN_MINIMUM_DISPCLK_Khz 100000 #define DCN_MINIMUM_DPPCLK_Khz 100000 @@ -242,14 +244,14 @@ struct wm_table { struct dummy_pstate_entry { unsigned int dram_speed_mts; - double dummy_pstate_latency_us; + unsigned int dummy_pstate_latency_us; }; struct clk_bw_params { unsigned int vram_type; unsigned int num_channels; unsigned int dram_channel_width_bytes; - unsigned int dispclk_vco_khz; + unsigned int dispclk_vco_khz; unsigned int dc_mode_softmax_memclk; unsigned int max_memclk_mhz; struct clk_limit_table clk_table; 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 885ba34beb7e..12282f96dfe1 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 @@ -97,11 +97,6 @@ enum dentist_divider_range { #define CLK_COMMON_REG_LIST_DCN_BASE() \ SR(DENTIST_DISPCLK_CNTL) -#define VBIOS_SMU_MSG_BOX_REG_LIST_RV() \ - .MP1_SMN_C2PMSG_91 = mmMP1_SMN_C2PMSG_91, \ - .MP1_SMN_C2PMSG_83 = mmMP1_SMN_C2PMSG_83, \ - .MP1_SMN_C2PMSG_67 = mmMP1_SMN_C2PMSG_67 - #define CLK_COMMON_REG_LIST_DCN_201() \ SR(DENTIST_DISPCLK_CNTL), \ CLK_SRI(CLK4_CLK_PLL_REQ, CLK4, 0), \ @@ -113,7 +108,7 @@ enum dentist_divider_range { CLK_SRI(CLK3_CLK2_DFS_CNTL, CLK3, 0) #define CLK_REG_LIST_DCN3() \ - CLK_COMMON_REG_LIST_DCN_BASE(), \ + SR(DENTIST_DISPCLK_CNTL), \ CLK_SRI(CLK0_CLK_PLL_REQ, CLK02, 0), \ CLK_SRI(CLK0_CLK2_DFS_CNTL, CLK02, 0) @@ -207,35 +202,22 @@ enum dentist_divider_range { type DENTIST_DISPCLK_WDIVIDER; \ type DENTIST_DISPCLK_CHG_DONE; -/* - *************************************************************************************** - ****************** Clock Manager Private Structures *********************************** - *************************************************************************************** - */ #define CLK20_REG_FIELD_LIST(type) \ type DENTIST_DPPCLK_WDIVIDER; \ type DENTIST_DPPCLK_CHG_DONE; \ type FbMult_int; \ type FbMult_frac; -#define VBIOS_SMU_REG_FIELD_LIST(type) \ - type CONTENT; - -struct clk_mgr_shift { - CLK_REG_FIELD_LIST(uint8_t) - CLK20_REG_FIELD_LIST(uint8_t) - VBIOS_SMU_REG_FIELD_LIST(uint32_t) -}; - -struct clk_mgr_mask { - CLK_REG_FIELD_LIST(uint32_t) - CLK20_REG_FIELD_LIST(uint32_t) - VBIOS_SMU_REG_FIELD_LIST(uint32_t) -}; +/* + *************************************************************************************** + ****************** Clock Manager Private Structures *********************************** + *************************************************************************************** + */ struct clk_mgr_registers { uint32_t DPREFCLK_CNTL; uint32_t DENTIST_DISPCLK_CNTL; + uint32_t CLK4_CLK2_CURRENT_CNT; uint32_t CLK4_CLK_PLL_REQ; @@ -264,10 +246,16 @@ struct clk_mgr_registers { uint32_t CLK0_CLK1_DFS_CNTL; uint32_t CLK0_CLK3_DFS_CNTL; uint32_t CLK0_CLK4_DFS_CNTL; +}; - uint32_t MP1_SMN_C2PMSG_67; - uint32_t MP1_SMN_C2PMSG_83; - uint32_t MP1_SMN_C2PMSG_91; +struct clk_mgr_shift { + CLK_REG_FIELD_LIST(uint8_t) + CLK20_REG_FIELD_LIST(uint8_t) +}; + +struct clk_mgr_mask { + CLK_REG_FIELD_LIST(uint32_t) + CLK20_REG_FIELD_LIST(uint32_t) }; enum clock_type { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h index 305fdc127bfc..1511400fc56b 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h @@ -33,6 +33,8 @@ * blocks for the Data Fabric Interface that are not clock/power gated. */ +#include "dc/dc_hw_types.h" + enum dcc_control { dcc_control__256_256_xxx, dcc_control__128_128_xxx, @@ -147,6 +149,17 @@ struct hubbub_funcs { enum segment_order *segment_order_horz, enum segment_order *segment_order_vert); + bool (*dcc_support_swizzle_addr3)( + enum swizzle_mode_addr3_values swizzle, + unsigned int plane_pitch, + unsigned int bytes_per_element, + enum segment_order *segment_order_horz, + enum segment_order *segment_order_vert); + + bool (*dcc_support_pixel_format_plane0_plane1)( + enum surface_pixel_format format, + unsigned int *plane0_bpe, + unsigned int *plane1_bpe); bool (*dcc_support_pixel_format)( enum surface_pixel_format format, unsigned int *bytes_per_element); @@ -201,6 +214,8 @@ struct hubbub_funcs { void (*set_request_limit)(struct hubbub *hubbub, int memory_channel_count, int words_per_channel); void (*dchubbub_init)(struct hubbub *hubbub); void (*get_mall_en)(struct hubbub *hubbub, unsigned int *mall_in_use); + void (*program_det_segments)(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_seg); + void (*program_compbuf_segments)(struct hubbub *hubbub, unsigned compbuf_size_seg, bool safe_to_increase); }; struct hubbub { 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 ca8de345d039..9ac7fc717a92 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -329,6 +329,10 @@ struct dpp_funcs { void (*dpp_get_gamut_remap)(struct dpp *dpp_base, struct dpp_grph_csc_adjustment *adjust); + void (*set_cursor_matrix)( + struct dpp *dpp_base, + enum dc_color_space color_space, + struct dc_csc_transform cursor_csc_color_matrix); }; 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 72610cd7eae0..bcd7b22a1627 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hubp.h @@ -41,6 +41,8 @@ #include "mem_input.h" #include "cursor_reg_cache.h" +#include "dml2/dml21/inc/dml_top_dchub_registers.h" + #define OPP_ID_INVALID 0xf #define MAX_TTU 0xffffff @@ -65,6 +67,37 @@ enum hubp_ind_block_size { hubp_ind_block_64b_no_128bcl, }; +enum hubp_3dlut_fl_mode { + hubp_3dlut_fl_mode_disable = 0, + hubp_3dlut_fl_mode_native_1 = 1, + hubp_3dlut_fl_mode_native_2 = 2, + hubp_3dlut_fl_mode_transform = 3 +}; + +enum hubp_3dlut_fl_format { + hubp_3dlut_fl_format_unorm_12msb_bitslice = 0, + hubp_3dlut_fl_format_unorm_12lsb_bitslice = 1, + hubp_3dlut_fl_format_float_fp1_5_10 = 2 +}; + +enum hubp_3dlut_fl_addressing_mode { + hubp_3dlut_fl_addressing_mode_sw_linear = 0, + hubp_3dlut_fl_addressing_mode_simple_linear = 1 +}; + +enum hubp_3dlut_fl_width { + hubp_3dlut_fl_width_17 = 17, + hubp_3dlut_fl_width_33 = 33, + hubp_3dlut_fl_width_transformed = 4916 +}; + +enum hubp_3dlut_fl_crossbar_bit_slice { + hubp_3dlut_fl_crossbar_bit_slice_0_15 = 0, + hubp_3dlut_fl_crossbar_bit_slice_16_31 = 1, + hubp_3dlut_fl_crossbar_bit_slice_32_47 = 2, + hubp_3dlut_fl_crossbar_bit_slice_48_63 = 3 +}; + struct hubp { const struct hubp_funcs *funcs; struct dc_context *ctx; @@ -211,17 +244,36 @@ struct hubp_funcs { bool (*hubp_in_blank)(struct hubp *hubp); void (*hubp_soft_reset)(struct hubp *hubp, bool reset); + void (*hubp_set_flip_int)(struct hubp *hubp); + void (*hubp_update_force_pstate_disallow)(struct hubp *hubp, bool allow); void (*hubp_update_force_cursor_pstate_disallow)(struct hubp *hubp, bool allow); void (*hubp_update_mall_sel)(struct hubp *hubp, uint32_t mall_sel, bool c_cursor); void (*hubp_prepare_subvp_buffering)(struct hubp *hubp, bool enable); - - void (*hubp_set_flip_int)(struct hubp *hubp); + void (*hubp_surface_update_lock)(struct hubp *hubp, + bool lock); void (*program_extended_blank)(struct hubp *hubp, unsigned int min_dst_y_next_start_optimized); void (*hubp_wait_pipe_read_start)(struct hubp *hubp); + 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); + 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, bool protection_enabled); + 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); + int (*hubp_get_3dlut_fl_done)(struct hubp *hubp); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h index 86c12cd6f47d..5f6c7daa14d9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mem_input.h @@ -29,6 +29,7 @@ #include "include/grph_object_id.h" #include "dml/display_mode_structs.h" +#include "dml2/dml21/inc/dml_top_dchub_registers.h" struct dchub_init_data; struct cstate_pstate_watermarks_st { @@ -45,7 +46,7 @@ struct dcn_watermarks { uint32_t urgent_ns; uint32_t frac_urg_bw_nom; uint32_t frac_urg_bw_flip; - int32_t urgent_latency_ns; + uint32_t urgent_latency_ns; struct cstate_pstate_watermarks_st cstate_pstate; uint32_t usr_retraining_ns; }; @@ -57,6 +58,12 @@ union dcn_watermark_set { struct dcn_watermarks c; struct dcn_watermarks d; }; // legacy + struct { + struct dml2_dchub_watermark_regs a; + struct dml2_dchub_watermark_regs b; + struct dml2_dchub_watermark_regs c; + struct dml2_dchub_watermark_regs d; + } dcn4; //dcn4+ }; struct dce_watermarks { 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 34a398f23fc6..dd786600668f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -96,6 +96,29 @@ enum mpcc_alpha_blend_mode { MPCC_ALPHA_BLEND_MODE_GLOBAL_ALPHA }; +enum mpcc_movable_cm_location { + MPCC_MOVABLE_CM_LOCATION_BEFORE, + 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, + MCM_LUT_SHAPER +}; + +union mcm_lut_params { + const struct pwl_params *pwl; + const struct tetrahedral_params *lut3d; +}; + /** * struct mpcc_blnd_cfg - MPCC blending configuration */ @@ -163,6 +186,7 @@ struct mpcc_blnd_cfg { struct mpc_grph_gamut_adjustment { struct fixed31_32 temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE]; enum graphics_gamut_adjust_type gamut_adjust_type; + enum mpcc_gamut_remap_id mpcc_gamut_remap_block_id; }; struct mpcc_sm_cfg { @@ -537,13 +561,21 @@ struct mpc_funcs { int (*release_rmu)(struct mpc *mpc, int mpcc_id); unsigned int (*get_mpc_out_mux)( - struct mpc *mpc, - int opp_id); + struct mpc *mpc, + int opp_id); void (*set_bg_color)(struct mpc *mpc, struct tg_color *bg_color, int mpcc_id); void (*set_mpc_mem_lp_mode)(struct mpc *mpc); + void (*set_movable_cm_location)(struct mpc *mpc, enum mpcc_movable_cm_location location, int mpcc_id); + void (*update_3dlut_fast_load_select)(struct mpc *mpc, int mpcc_id, int hubp_idx); + void (*get_3dlut_fast_load_status)(struct mpc *mpc, int mpcc_id, uint32_t *done, uint32_t *soft_underflow, uint32_t *hard_underflow); + 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 (*program_lut_read_write_control)(struct mpc *mpc, const enum MCM_LUT_ID id, bool lut_bank_a, int mpcc_id); + 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); }; #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 a2c57676b08d..5aa2f1a1fb83 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/transform.h @@ -29,6 +29,7 @@ #include "hw_shared.h" #include "dc_hw_types.h" #include "fixed31_32.h" +#include "spl/dc_spl_types.h" #include "spl/dc_spl_types.h" @@ -163,6 +164,8 @@ struct scaler_data { struct sharpness_adj sharpness; enum 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; }; struct transform_funcs { @@ -245,6 +248,15 @@ struct transform_funcs { struct transform *xfm_base, const struct dc_cursor_attributes *attr); + bool (*transform_program_blnd_lut)( + struct transform *xfm, + const struct pwl_params *params); + bool (*transform_program_shaper_lut)( + struct transform *xfm, + const struct pwl_params *params); + bool (*transform_program_3dlut)( + struct transform *xfm, + struct tetrahedral_params *params); }; const uint16_t *get_filter_2tap_16p(void); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 361ad6b16b96..5c980644591d 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -29,6 +29,7 @@ #include "core_status.h" #include "dal_asic_id.h" #include "dm_pp_smu.h" +#include "spl/dc_spl.h" #define MEMORY_TYPE_MULTIPLIER_CZ 4 #define MEMORY_TYPE_HBM 2 @@ -77,11 +78,9 @@ struct resource_create_funcs { struct hpo_dp_stream_encoder *(*create_hpo_dp_stream_encoder)( enum engine_id eng_id, struct dc_context *ctx); - struct hpo_dp_link_encoder *(*create_hpo_dp_link_encoder)( uint8_t inst, struct dc_context *ctx); - struct dce_hwseq *(*create_hwseq)( struct dc_context *ctx); }; @@ -620,6 +619,11 @@ enum dc_status update_dp_encoder_resources_for_test_harness(const struct dc *dc, bool check_subvp_sw_cursor_fallback_req(const struct dc *dc, struct dc_stream_state *stream); +/* Get hw programming parameters container from pipe context + * @pipe_ctx: pipe context + * @dscl_prog_data: struct to hold programmable hw reg values + */ +struct dscl_prog_data *resource_get_dscl_prog_data(struct pipe_ctx *pipe_ctx); /* Setup dc callbacks for dml2 * @dc: the display core structure * @dml2_options: struct to hold callbacks diff --git a/drivers/gpu/drm/amd/display/dc/irq/Makefile b/drivers/gpu/drm/amd/display/dc/irq/Makefile index 2d4378780c1a..8ac36bdd4e1e 100644 --- a/drivers/gpu/drm/amd/display/dc/irq/Makefile +++ b/drivers/gpu/drm/amd/display/dc/irq/Makefile @@ -180,3 +180,12 @@ IRQ_DCN351 = irq_service_dcn351.o AMD_DAL_IRQ_DCN351= $(addprefix $(AMDDALPATH)/dc/irq/dcn351/,$(IRQ_DCN351)) AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCN351) + +############################################################################### +# DCN 401 +############################################################################### +IRQ_DCN401 = irq_service_dcn401.o + +AMD_DAL_IRQ_DCN401= $(addprefix $(AMDDALPATH)/dc/irq/dcn401/,$(IRQ_DCN401)) + +AMD_DISPLAY_FILES += $(AMD_DAL_IRQ_DCN401) diff --git a/drivers/gpu/drm/amd/display/dc/optc/Makefile b/drivers/gpu/drm/amd/display/dc/optc/Makefile index bb213335fb9f..29fb610c8660 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/optc/Makefile @@ -105,4 +105,10 @@ 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) endif + 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 874cf5d241ad..e3e70c1db040 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 @@ -330,8 +330,6 @@ struct dcn_optc_registers { SF(GSL_SOURCE_SELECT, GSL2_READY_SOURCE_SEL, mask_sh),\ SF(OTG0_OTG_GLOBAL_CONTROL2, MANUAL_FLOW_CONTROL_SEL, mask_sh) - - #define TG_COMMON_MASK_SH_LIST_DCN1_0(mask_sh)\ TG_COMMON_MASK_SH_LIST_DCN(mask_sh),\ SF(OTG0_OTG_TEST_PATTERN_PARAMETERS, OTG_TEST_PATTERN_INC0, mask_sh),\ @@ -569,7 +567,6 @@ struct dcn_optc_registers { #define TG_REG_FIELD_LIST_DCN3_2(type) \ type OTG_H_TIMING_DIV_MODE_MANUAL; - #define TG_REG_FIELD_LIST_DCN3_5(type) \ type OTG_CRC0_WINDOWA_X_START_READBACK;\ type OTG_CRC0_WINDOWA_X_END_READBACK;\ diff --git a/drivers/gpu/drm/amd/display/dc/resource/Makefile b/drivers/gpu/drm/amd/display/dc/resource/Makefile index db9048974d74..abc2405b7167 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/Makefile +++ b/drivers/gpu/drm/amd/display/dc/resource/Makefile @@ -198,4 +198,12 @@ AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN351) ############################################################################### +############################################################################### + +RESOURCE_DCN401 = dcn401_resource.o + +AMD_DAL_RESOURCE_DCN401 = $(addprefix $(AMDDALPATH)/dc/resource/dcn401/,$(RESOURCE_DCN401)) + +AMD_DISPLAY_FILES += $(AMD_DAL_RESOURCE_DCN401) + endif 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 abd76345d1e4..022d320be1d5 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 @@ -719,6 +719,7 @@ static const struct dc_debug_options debug_defaults_drv = { .force_disable_subvp = false, .exit_idle_opt_for_cursor_updates = true, .using_dml2 = false, + .using_dml21 = false, // TODO : Temporary for N-1 validation. Remove after N-1 is done. .enable_single_display_2to1_odm_policy = true, /* Must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/ 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 c9ec46c6b4c6..25333337461e 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -258,6 +258,17 @@ enum { #define ASICREV_IS_GC_11_0_3(eChipRev) (eChipRev >= GC_11_0_3_A0 && eChipRev < GC_11_UNKNOWN) #define ASICREV_IS_GC_11_0_4(eChipRev) (eChipRev >= GC_11_0_4_A0 && eChipRev < GC_11_UNKNOWN) +#define AMDGPU_FAMILY_GC_12_0_0 152 /* GC 12.0.0 */ + +enum { + GC_12_0_0_A0 = 0x50, + GC_12_0_1_A0 = 0x40, + GC_12_UNKNOWN = 0xFF, +}; + +#define ASICREV_IS_DCN4(eChipRev) (eChipRev >= GC_12_0_1_A0 && eChipRev < GC_12_0_0_A0) +#define ASICREV_IS_DCN401(eChipRev) (eChipRev >= GC_12_0_0_A0 && eChipRev < GC_12_UNKNOWN) + /* * ASIC chip ID */ diff --git a/drivers/gpu/drm/amd/display/include/dal_types.h b/drivers/gpu/drm/amd/display/include/dal_types.h index 447768dec887..654387cf057f 100644 --- a/drivers/gpu/drm/amd/display/include/dal_types.h +++ b/drivers/gpu/drm/amd/display/include/dal_types.h @@ -63,6 +63,7 @@ enum dce_version { DCN_VERSION_3_21, DCN_VERSION_3_5, DCN_VERSION_3_51, + DCN_VERSION_4_01, DCN_VERSION_MAX }; -- cgit From dc2be9c68ffb2d2b960e6b1835327438b929b814 Mon Sep 17 00:00:00 2001 From: Ethan Bitnun Date: Wed, 10 Apr 2024 17:16:35 -0400 Subject: drm/amd/display: Block FPO According to Luminance Delta [Description] - Block FPO if the max stretch refresh rate is low enough to cause a flicker by storing the maximum safe refresh decrease from nominal in stream. - Brought over various Freesync Luminance functions to dc. Use these new functions to block fpo if we will flicker. - Generalized increase/reduce dependent functions to reduce code clutter and allow for easier use. - Added a debug option to enable the feature. Disabled by default. Co-authored-by: Ethan Bitnun Reviewed-by: Dillon Varone Acked-by: Aurabindo Pillai Signed-off-by: Ethan Bitnun Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 228 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dc_stream.h | 14 ++ drivers/gpu/drm/amd/display/dc/dc_stream_priv.h | 24 +++ .../amd/display/dc/dcn32/dcn32_resource_helpers.c | 9 +- 5 files changed, 274 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') 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 5c7e4884cac2..d3201b0b3a09 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -35,6 +35,8 @@ #include "dc_stream_priv.h" #define DC_LOGGER dc->ctx->logger +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#define MAX(x, y) ((x > y) ? x : y) /******************************************************************************* * Private functions @@ -781,3 +783,229 @@ void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream) } } +/* + * Finds the greatest index in refresh_rate_hz that contains a value <= refresh + */ +static int dc_stream_get_nearest_smallest_index(struct dc_stream_state *stream, int refresh) +{ + for (int i = 0; i < (LUMINANCE_DATA_TABLE_SIZE - 1); ++i) { + if ((stream->lumin_data.refresh_rate_hz[i] <= refresh) && (refresh < stream->lumin_data.refresh_rate_hz[i + 1])) { + return i; + } + } + return 9; +} + +/* + * Finds a corresponding brightness for a given refresh rate between 2 given indices, where index1 < index2 + */ +static int dc_stream_get_brightness_millinits_linear_interpolation (struct dc_stream_state *stream, + int index1, + int index2, + int refresh_hz) +{ + int slope = 0; + if (stream->lumin_data.refresh_rate_hz[index2] != stream->lumin_data.refresh_rate_hz[index1]) { + slope = (stream->lumin_data.luminance_millinits[index2] - stream->lumin_data.luminance_millinits[index1]) / + (stream->lumin_data.refresh_rate_hz[index2] - stream->lumin_data.refresh_rate_hz[index1]); + } + + int y_intercept = stream->lumin_data.luminance_millinits[index2] - slope * stream->lumin_data.refresh_rate_hz[index2]; + + return (y_intercept + refresh_hz * slope); +} + +/* + * Finds a corresponding refresh rate for a given brightness between 2 given indices, where index1 < index2 + */ +static int dc_stream_get_refresh_hz_linear_interpolation (struct dc_stream_state *stream, + int index1, + int index2, + int brightness_millinits) +{ + int slope = 1; + if (stream->lumin_data.refresh_rate_hz[index2] != stream->lumin_data.refresh_rate_hz[index1]) { + slope = (stream->lumin_data.luminance_millinits[index2] - stream->lumin_data.luminance_millinits[index1]) / + (stream->lumin_data.refresh_rate_hz[index2] - stream->lumin_data.refresh_rate_hz[index1]); + } + + int y_intercept = stream->lumin_data.luminance_millinits[index2] - slope * stream->lumin_data.refresh_rate_hz[index2]; + + return ((brightness_millinits - y_intercept) / slope); +} + +/* + * Finds the current brightness in millinits given a refresh rate + */ +static int dc_stream_get_brightness_millinits_from_refresh (struct dc_stream_state *stream, int refresh_hz) +{ + int nearest_smallest_index = dc_stream_get_nearest_smallest_index(stream, refresh_hz); + int nearest_smallest_value = stream->lumin_data.refresh_rate_hz[nearest_smallest_index]; + + if (nearest_smallest_value == refresh_hz) + return stream->lumin_data.luminance_millinits[nearest_smallest_index]; + + if (nearest_smallest_index >= 9) + return dc_stream_get_brightness_millinits_linear_interpolation(stream, nearest_smallest_index - 1, nearest_smallest_index, refresh_hz); + + if (nearest_smallest_value == stream->lumin_data.refresh_rate_hz[nearest_smallest_index + 1]) + return stream->lumin_data.luminance_millinits[nearest_smallest_index]; + + return dc_stream_get_brightness_millinits_linear_interpolation(stream, nearest_smallest_index, nearest_smallest_index + 1, refresh_hz); +} + +/* + * Finds the lowest refresh rate that can be achieved + * from starting_refresh_hz while staying within flicker criteria + */ +static int dc_stream_calculate_flickerless_refresh_rate(struct dc_stream_state *stream, + int current_brightness, + int starting_refresh_hz, + bool is_gaming, + bool search_for_max_increase) +{ + int nearest_smallest_index = dc_stream_get_nearest_smallest_index(stream, starting_refresh_hz); + + int flicker_criteria_millinits = is_gaming ? + stream->lumin_data.flicker_criteria_milli_nits_GAMING : + stream->lumin_data.flicker_criteria_milli_nits_STATIC; + + int safe_upper_bound = current_brightness + flicker_criteria_millinits; + int safe_lower_bound = current_brightness - flicker_criteria_millinits; + int lumin_millinits_temp = 0; + + int offset = -1; + if (search_for_max_increase) { + offset = 1; + } + + /* + * Increments up or down by 1 depending on search_for_max_increase + */ + for (int i = nearest_smallest_index; (i > 0 && !search_for_max_increase) || (i < (LUMINANCE_DATA_TABLE_SIZE - 1) && search_for_max_increase); i += offset) { + + lumin_millinits_temp = stream->lumin_data.luminance_millinits[i + offset]; + + if ((lumin_millinits_temp >= safe_upper_bound) || (lumin_millinits_temp <= safe_lower_bound)) { + + if (stream->lumin_data.refresh_rate_hz[i + offset] == stream->lumin_data.refresh_rate_hz[i]) + return stream->lumin_data.refresh_rate_hz[i]; + + int target_brightness = (stream->lumin_data.luminance_millinits[i + offset] >= (current_brightness + flicker_criteria_millinits)) ? + current_brightness + flicker_criteria_millinits : + current_brightness - flicker_criteria_millinits; + + int refresh = 0; + + /* + * Need the second input to be < third input for dc_stream_get_refresh_hz_linear_interpolation + */ + if (search_for_max_increase) + refresh = dc_stream_get_refresh_hz_linear_interpolation(stream, i, i + offset, target_brightness); + else + refresh = dc_stream_get_refresh_hz_linear_interpolation(stream, i + offset, i, target_brightness); + + if (refresh == stream->lumin_data.refresh_rate_hz[i + offset]) + return stream->lumin_data.refresh_rate_hz[i + offset]; + + return refresh; + } + } + + if (search_for_max_increase) + return stream->lumin_data.refresh_rate_hz[LUMINANCE_DATA_TABLE_SIZE - 1]; + else + return stream->lumin_data.refresh_rate_hz[0]; +} + +/* + * Gets the max delta luminance within a specified refresh range + */ +static int dc_stream_get_max_delta_lumin_millinits(struct dc_stream_state *stream, int hz1, int hz2, bool isGaming) +{ + int lower_refresh_brightness = dc_stream_get_brightness_millinits_from_refresh (stream, hz1); + int higher_refresh_brightness = dc_stream_get_brightness_millinits_from_refresh (stream, hz2); + + int min = lower_refresh_brightness; + int max = higher_refresh_brightness; + + /* + * Static screen, therefore no need to scan through array + */ + if (!isGaming) { + if (lower_refresh_brightness >= higher_refresh_brightness) { + return lower_refresh_brightness - higher_refresh_brightness; + } + return higher_refresh_brightness - lower_refresh_brightness; + } + + min = MIN(lower_refresh_brightness, higher_refresh_brightness); + max = MAX(lower_refresh_brightness, higher_refresh_brightness); + + int nearest_smallest_index = dc_stream_get_nearest_smallest_index(stream, hz1); + + for (; nearest_smallest_index < (LUMINANCE_DATA_TABLE_SIZE - 1) && + stream->lumin_data.refresh_rate_hz[nearest_smallest_index + 1] <= hz2 ; nearest_smallest_index++) { + min = MIN(min, stream->lumin_data.luminance_millinits[nearest_smallest_index + 1]); + max = MAX(max, stream->lumin_data.luminance_millinits[nearest_smallest_index + 1]); + } + + return (max - min); +} + +/* + * Finds the highest refresh rate that can be achieved + * from starting_refresh_hz while staying within flicker criteria + */ +int dc_stream_calculate_max_flickerless_refresh_rate(struct dc_stream_state *stream, int starting_refresh_hz, bool is_gaming) +{ + if (!stream->lumin_data.is_valid) + return 0; + + int current_brightness = dc_stream_get_brightness_millinits_from_refresh(stream, starting_refresh_hz); + + return dc_stream_calculate_flickerless_refresh_rate(stream, + current_brightness, + starting_refresh_hz, + is_gaming, + true); +} + +/* + * Finds the lowest refresh rate that can be achieved + * from starting_refresh_hz while staying within flicker criteria + */ +int dc_stream_calculate_min_flickerless_refresh_rate(struct dc_stream_state *stream, int starting_refresh_hz, bool is_gaming) +{ + if (!stream->lumin_data.is_valid) + return 0; + + int current_brightness = dc_stream_get_brightness_millinits_from_refresh(stream, starting_refresh_hz); + + return dc_stream_calculate_flickerless_refresh_rate(stream, + current_brightness, + starting_refresh_hz, + is_gaming, + false); +} + +/* + * Determines if there will be a flicker when moving between 2 refresh rates + */ +bool dc_stream_is_refresh_rate_range_flickerless(struct dc_stream_state *stream, int hz1, int hz2, bool is_gaming) +{ + + /* + * Assume that we wont flicker if there is invalid data + */ + if (!stream->lumin_data.is_valid) + return false; + + int dl = dc_stream_get_max_delta_lumin_millinits(stream, hz1, hz2, is_gaming); + + int flicker_criteria_millinits = (is_gaming) ? + stream->lumin_data.flicker_criteria_milli_nits_GAMING : + stream->lumin_data.flicker_criteria_milli_nits_STATIC; + + return (dl <= flicker_criteria_millinits); +} diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9d235fc3525d..1e28a36a76e6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -456,6 +456,7 @@ struct dc_config { bool allow_0_dtb_clk; bool use_assr_psp_message; bool support_edp0_on_dp1; + unsigned int enable_fpo_flicker_detection; }; enum visual_confirm { diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index e5dbbc6089a5..3d0adf8838ca 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -160,6 +160,18 @@ struct dc_stream_debug_options { char force_odm_combine_segments; }; +#define LUMINANCE_DATA_TABLE_SIZE 10 + +struct luminance_data { + bool is_valid; + int refresh_rate_hz[LUMINANCE_DATA_TABLE_SIZE]; + int luminance_millinits[LUMINANCE_DATA_TABLE_SIZE]; + int flicker_criteria_milli_nits_GAMING; + int flicker_criteria_milli_nits_STATIC; + int nominal_refresh_rate; + int dm_max_decrease_from_nominal; +}; + struct dc_stream_state { // sink is deprecated, new code should not reference // this pointer @@ -286,6 +298,8 @@ struct dc_stream_state { bool vblank_synchronized; bool fpo_in_use; bool is_phantom; + + struct luminance_data lumin_data; }; #define ABM_LEVEL_IMMEDIATE_DISABLE 255 diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream_priv.h b/drivers/gpu/drm/amd/display/dc/dc_stream_priv.h index 7476fd52ce2b..ea13804f7b14 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream_priv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream_priv.h @@ -34,4 +34,28 @@ void dc_stream_destruct(struct dc_stream_state *stream); void dc_stream_assign_stream_id(struct dc_stream_state *stream); +/* + * Finds the highest refresh rate that can be achieved + * from starting_freq while staying within flicker criteria + */ +int dc_stream_calculate_max_flickerless_refresh_rate(struct dc_stream_state *stream, + int starting_refresh_hz, + bool is_gaming); + +/* + * Finds the lowest refresh rate that can be achieved + * from starting_freq while staying within flicker criteria + */ +int dc_stream_calculate_min_flickerless_refresh_rate(struct dc_stream_state *stream, + int starting_refresh_hz, + bool is_gaming); + +/* + * Determines if there will be a flicker when moving between 2 refresh rates + */ +bool dc_stream_is_refresh_rate_range_flickerless(struct dc_stream_state *stream, + int hz1, + int hz2, + bool is_gaming); + #endif // _DC_STREAM_PRIV_H_ diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index fbcd6f7bc993..6472da2c361e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -29,6 +29,7 @@ #include "dml/dcn32/display_mode_vba_util_32.h" #include "dml/dcn32/dcn32_fpu.h" #include "dc_state_priv.h" +#include "dc_stream_priv.h" static bool is_dual_plane(enum surface_pixel_format format) { @@ -459,7 +460,7 @@ static int get_frame_rate_at_max_stretch_100hz( } static bool is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch( - struct dc_stream_state *fpo_candidate_stream, uint32_t fpo_vactive_margin_us) + struct dc_stream_state *fpo_candidate_stream, uint32_t fpo_vactive_margin_us, int current_refresh_rate) { int refresh_rate_max_stretch_100hz; int min_refresh_100hz; @@ -473,6 +474,10 @@ static bool is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch( if (refresh_rate_max_stretch_100hz < min_refresh_100hz) return false; + if (fpo_candidate_stream->ctx->dc->config.enable_fpo_flicker_detection > 0 && + !dc_stream_is_refresh_rate_range_flickerless(fpo_candidate_stream, (refresh_rate_max_stretch_100hz / 100), current_refresh_rate, false)) + return false; + return true; } @@ -569,7 +574,7 @@ struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stre return NULL; fpo_vactive_margin_us = is_fpo_vactive ? dc->debug.fpo_vactive_margin_us : 0; // For now hardcode the FPO + Vactive stretch margin to be 2000us - if (!is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(fpo_candidate_stream, fpo_vactive_margin_us)) + if (!is_refresh_rate_support_mclk_switch_using_fw_based_vblank_stretch(fpo_candidate_stream, fpo_vactive_margin_us, refresh_rate)) return NULL; if (!fpo_candidate_stream->allow_freesync) -- cgit From 84d3c6b05c8cf4e015ba7b79201783ea6f3e39e2 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 14 Apr 2024 14:28:32 -0400 Subject: drm/amd/display: 3.2.282 Summary: * Changes across DSC, MST, DMCUB, Panel Replay and misc fixes. * Fixes to cursor programming sequence * Add some missing register defs * Formatting/Sytle fixes Acked-by: Aurabindo Pillai Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1e28a36a76e6..a3ebe4f00779 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,7 +55,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.281" +#define DC_VER "3.2.282" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From ae308e93db35e8e7652d3ff1696adfc240bc1749 Mon Sep 17 00:00:00 2001 From: Iswara Nagulendran Date: Thu, 11 Apr 2024 14:39:50 -0400 Subject: drm/amd/display: Restrict multi-disp support for in-game FAMS [HOW&WHY] In multi-monitor cases the VBLANK stretch that is required to align both monitors may be so large that it may create issues for gaming performance. Use debug value to restrict in-game FAMS support for multi-disp use case. Reviewed-by: Harry Vanzylldejong Acked-by: Wayne Lin Signed-off-by: Iswara Nagulendran Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 8 +++++++- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c | 4 +++- drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a3ebe4f00779..3048d5a0e87d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -499,6 +499,12 @@ enum dcc_option { DCC_HALF_REQ_DISALBE = 2, }; +enum in_game_fams_config { + INGAME_FAMS_SINGLE_DISP_ENABLE, // enable in-game fams + INGAME_FAMS_DISABLE, // disable in-game fams + INGAME_FAMS_MULTI_DISP_ENABLE, //enable in-game fams for multi-display +}; + /** * enum pipe_split_policy - Pipe split strategy supported by DCN * @@ -951,7 +957,7 @@ struct dc_debug_options { /* Enable dmub aux for legacy ddc */ bool enable_dmub_aux_for_legacy_ddc; bool disable_fams; - bool disable_fams_gaming; + enum in_game_fams_config disable_fams_gaming; /* FEC/PSR1 sequence enable delay in 100us */ uint8_t fec_enable_delay_in100us; bool enable_driver_sequence_debug; diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index 6472da2c361e..a8c36eda1d09 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -580,7 +580,9 @@ struct dc_stream_state *dcn32_can_support_mclk_switch_using_fw_based_vblank_stre if (!fpo_candidate_stream->allow_freesync) return NULL; - if (fpo_candidate_stream->vrr_active_variable && dc->debug.disable_fams_gaming) + if (fpo_candidate_stream->vrr_active_variable && + ((dc->debug.disable_fams_gaming == INGAME_FAMS_DISABLE) || + (context->stream_count > 1 && !(dc->debug.disable_fams_gaming == INGAME_FAMS_MULTI_DISP_ENABLE)))) return NULL; return fpo_candidate_stream; 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 fa1305f04341..1ce727351c39 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 @@ -1996,7 +1996,7 @@ bool dcn30_can_support_mclk_switch_using_fw_based_vblank_stretch(struct dc *dc, if (!context->streams[0]->allow_freesync) return false; - if (context->streams[0]->vrr_active_variable && dc->debug.disable_fams_gaming) + if (context->streams[0]->vrr_active_variable && (dc->debug.disable_fams_gaming == INGAME_FAMS_DISABLE)) return false; context->streams[0]->fpo_in_use = true; -- cgit From f2303026a5b6327247ba61152d00199b2d1be294 Mon Sep 17 00:00:00 2001 From: Daniel Miess Date: Wed, 24 Apr 2024 16:49:13 +0800 Subject: drm/amd/display: Enable RCO for PHYSYMCLK in DCN35 [Why & How] Enable root clock optimization for PHYSYMCLK and only disable it when it's actively being used v2: Fix array-index-out-of-bounds in dcn35_calc_blocks_to_gate Reviewed-by: Roman Li Reviewed-by: Charlene Liu Acked-by: Wayne Lin Signed-off-by: Daniel Miess Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c | 45 ---------------------- .../drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 32 +++++++++++++++ .../drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h | 2 + .../gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c | 1 + .../drm/amd/display/dc/hwss/dcn351/dcn351_init.c | 1 + .../drm/amd/display/dc/hwss/hw_sequencer_private.h | 4 ++ 7 files changed, 41 insertions(+), 45 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 3048d5a0e87d..dd8940c2a4bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -724,6 +724,7 @@ enum pg_hw_pipe_resources { PG_OPTC, PG_DPSTREAM, PG_HDMISTREAM, + PG_PHYSYMCLK, PG_HW_PIPE_RESOURCES_NUM_ELEMENT }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c index 4b282b7e0996..795320a25fd2 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c @@ -461,32 +461,22 @@ static void dccg35_set_physymclk_root_clock_gating( case 0: REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, PHYASYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYA_REFCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); break; case 1: REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, PHYBSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYB_REFCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); break; case 2: REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, PHYCSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYC_REFCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); break; case 3: REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, PHYDSYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYD_REFCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); break; case 4: REG_UPDATE(DCCG_GATE_DISABLE_CNTL2, PHYESYMCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYE_REFCLK_ROOT_GATE_DISABLE, enable ? 1 : 0); break; default: BREAK_TO_DEBUGGER(); @@ -509,16 +499,10 @@ static void dccg35_set_physymclk( REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_EN, 1, PHYASYMCLK_SRC_SEL, clk_src); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYA_REFCLK_ROOT_GATE_DISABLE, 0); } else { REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_EN, 0, PHYASYMCLK_SRC_SEL, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYA_REFCLK_ROOT_GATE_DISABLE, 1); } break; case 1: @@ -526,16 +510,10 @@ static void dccg35_set_physymclk( REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_EN, 1, PHYBSYMCLK_SRC_SEL, clk_src); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYB_REFCLK_ROOT_GATE_DISABLE, 0); } else { REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_EN, 0, PHYBSYMCLK_SRC_SEL, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYB_REFCLK_ROOT_GATE_DISABLE, 1); } break; case 2: @@ -543,16 +521,10 @@ static void dccg35_set_physymclk( REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_EN, 1, PHYCSYMCLK_SRC_SEL, clk_src); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYC_REFCLK_ROOT_GATE_DISABLE, 0); } else { REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_EN, 0, PHYCSYMCLK_SRC_SEL, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYC_REFCLK_ROOT_GATE_DISABLE, 1); } break; case 3: @@ -560,16 +532,10 @@ static void dccg35_set_physymclk( REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_EN, 1, PHYDSYMCLK_SRC_SEL, clk_src); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYD_REFCLK_ROOT_GATE_DISABLE, 0); } else { REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_EN, 0, PHYDSYMCLK_SRC_SEL, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYD_REFCLK_ROOT_GATE_DISABLE, 1); } break; case 4: @@ -577,16 +543,10 @@ static void dccg35_set_physymclk( REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_EN, 1, PHYESYMCLK_SRC_SEL, clk_src); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYE_REFCLK_ROOT_GATE_DISABLE, 0); } else { REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_EN, 0, PHYESYMCLK_SRC_SEL, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL4, -// PHYE_REFCLK_ROOT_GATE_DISABLE, 1); } break; default: @@ -724,11 +684,6 @@ void dccg35_init(struct dccg *dccg) dccg35_set_dpstreamclk_root_clock_gating(dccg, otg_inst, false); } - if (dccg->ctx->dc->debug.root_clock_optimization.bits.physymclk) - for (otg_inst = 0; otg_inst < 5; otg_inst++) - dccg35_set_physymclk_root_clock_gating(dccg, otg_inst, - false); - if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpp) for (otg_inst = 0; otg_inst < 4; otg_inst++) dccg35_set_dppclk_root_clock_gating(dccg, otg_inst, 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 d4989d15e2f1..1c71a5d4ac5d 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 @@ -506,6 +506,17 @@ void dcn35_dpstream_root_clock_control(struct dce_hwseq *hws, unsigned int dp_hp } } +void dcn35_physymclk_root_clock_control(struct dce_hwseq *hws, unsigned int phy_inst, bool clock_on) +{ + if (!hws->ctx->dc->debug.root_clock_optimization.bits.physymclk) + return; + + if (hws->ctx->dc->res_pool->dccg->funcs->set_physymclk_root_clock_gating) { + hws->ctx->dc->res_pool->dccg->funcs->set_physymclk_root_clock_gating( + hws->ctx->dc->res_pool->dccg, phy_inst, clock_on); + } +} + void dcn35_dsc_pg_control( struct dce_hwseq *hws, unsigned int dsc_inst, @@ -1020,6 +1031,13 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, 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; } + + 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]; @@ -1117,6 +1135,10 @@ void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, } } + 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->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]) { @@ -1267,6 +1289,11 @@ void dcn35_root_clock_control(struct dc *dc, 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]) { @@ -1292,6 +1319,11 @@ void dcn35_root_clock_control(struct dc *dc, 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); + } } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h index a731c8880d60..bc05beba5f2c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h @@ -39,6 +39,8 @@ void dcn35_dpp_root_clock_control(struct dce_hwseq *hws, unsigned int dpp_inst, void dcn35_dpstream_root_clock_control(struct dce_hwseq *hws, unsigned int dp_hpo_inst, bool clock_on); +void dcn35_physymclk_root_clock_control(struct dce_hwseq *hws, unsigned int phy_inst, bool clock_on); + void dcn35_enable_power_gating_plane(struct dce_hwseq *hws, bool enable); void dcn35_set_dmu_fgcg(struct dce_hwseq *hws, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c index 0e87f3503265..7f2cbfac9099 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c @@ -149,6 +149,7 @@ static const struct hwseq_private_funcs dcn35_private_funcs = { .enable_power_gating_plane = dcn35_enable_power_gating_plane, .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, .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, .update_odm = dcn35_update_odm, .set_hdr_multiplier = dcn10_set_hdr_multiplier, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c index ff772665d1ae..91484b71b7da 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c @@ -148,6 +148,7 @@ static const struct hwseq_private_funcs dcn351_private_funcs = { .enable_power_gating_plane = dcn35_enable_power_gating_plane, .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, .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, .update_odm = dcn35_update_odm, .set_hdr_multiplier = dcn10_set_hdr_multiplier, 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 939832372baf..7553d6816d36 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 @@ -124,6 +124,10 @@ struct hwseq_private_funcs { struct dce_hwseq *hws, unsigned int dpp_inst, bool clock_on); + void (*physymclk_root_clock_control)( + struct dce_hwseq *hws, + unsigned int phy_inst, + bool clock_on); void (*dpp_pg_control)(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on); -- cgit From cb696a88fa582e0c236dffefd2fe6b5840f4e742 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 21 Apr 2024 20:20:01 -0400 Subject: drm/amd/display: 3.2.283 This version brings along following fixes: - Disable seamless boot on 128b/132b encoding - Have cursor and surface updates together - Change ASSR disable sequence to avoid corruption - Fix few IPS problems - Enable Replay for DCN315 - Fix few ODM problems - Fix FEC_READY write timing - Fix few FPO problems - Adjust DML21 gpuvm_enable assignment - Fix divide by 0 error in VM environment - Fix few DCN35 problems - Fix flickering on DCN321 - Fix mst resume problem - Fix multi-disp FAMS problem - Refactor Replay - Update some of the dcn303 parameters - Enable legacy fast update for dcn301 - Add VCO parameter for DCN31 FPU - Fix problems reported by Coverity Acked-by: Wayne Lin Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index dd8940c2a4bf..b6e92dda4b2d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,7 +55,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.282" +#define DC_VER "3.2.283" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 4482b4f6c2cce51a3e28eb814ea61ac5a1690412 Mon Sep 17 00:00:00 2001 From: Sreeja Golui Date: Thu, 18 Apr 2024 15:54:13 -0400 Subject: drm/amd/display: Providing a mechanism to have a custom pwm frequency [Why] Providing a mechanism to manipulate the pwm frequency on the individual GPUs and monitor the transition during the switch. [How] Added a variable in dc_debug_options data structure. Using this variable to call the newly added command on the firmware. Reviewed-by: Harry Vanzylldejong Acked-by: Tom Chung Signed-off-by: Sreeja Golui Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c | 14 ++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.h | 3 +++ 3 files changed, 18 insertions(+) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index b6e92dda4b2d..235e43e10799 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1026,6 +1026,7 @@ struct dc_debug_options { bool disable_extblankadj; bool enable_idle_reg_checks; unsigned int static_screen_wait_frames; + uint32_t pwm_freq; bool force_chroma_subsampling_1tap; bool disable_422_left_edge_pixel; bool dml21_force_pstate_method; diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c index 20c6fe48567f..573898984726 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.c @@ -70,6 +70,7 @@ static uint32_t dcn31_panel_cntl_hw_init(struct panel_cntl *panel_cntl) struct dcn31_panel_cntl *dcn31_panel_cntl = TO_DCN31_PANEL_CNTL(panel_cntl); struct dc_dmub_srv *dc_dmub_srv = panel_cntl->ctx->dmub_srv; union dmub_rb_cmd cmd; + uint32_t freq_to_set = panel_cntl->ctx->dc->debug.pwm_freq; if (!dc_dmub_srv) return 0; @@ -96,6 +97,19 @@ static uint32_t dcn31_panel_cntl_hw_init(struct panel_cntl *panel_cntl) panel_cntl->stored_backlight_registers.PANEL_PWRSEQ_REF_DIV2 = cmd.panel_cntl.data.bl_pwm_ref_div2; + if (freq_to_set >= MIN_DEBUG_FREQ_HZ && freq_to_set <= MAX_DEBUG_FREQ_HZ) { + uint32_t xtal = panel_cntl->ctx->dc->res_pool->ref_clocks.dccg_ref_clock_inKhz; + + memset(&cmd, 0, sizeof(cmd)); + cmd.panel_cntl.header.type = DMUB_CMD__PANEL_CNTL; + cmd.panel_cntl.header.sub_type = DMUB_CMD__PANEL_DEBUG_PWM_FREQ; + cmd.panel_cntl.header.payload_bytes = sizeof(cmd.panel_cntl.data); + cmd.panel_cntl.data.pwrseq_inst = dcn31_panel_cntl->base.pwrseq_inst; + cmd.panel_cntl.data.bl_pwm_cntl = xtal; + cmd.panel_cntl.data.bl_pwm_period_cntl = freq_to_set; + if (!dc_wake_and_execute_dmub_cmd(dc_dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) + return 0; + } return cmd.panel_cntl.data.current_backlight; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.h index d33ccd6ef8c3..8cf0259e211e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_panel_cntl.h @@ -29,6 +29,9 @@ #include "panel_cntl.h" #include "dce/dce_panel_cntl.h" +#define MIN_DEBUG_FREQ_HZ 200 +#define MAX_DEBUG_FREQ_HZ 6250 + struct dcn31_panel_cntl { struct panel_cntl base; }; -- cgit From ede045c091b19f8ac702f717f1fc1279b62bdd97 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 28 Apr 2024 20:22:18 -0400 Subject: drm/amd/display: 3.2.284 This version brings along following fixes: - Fix some problems reported by Coverity - Fix idle optimization checks for multi-display and dual eDP - Fix incorrect size calculation for loop - Fix DSC-re-computing - Add Replay capability and state in debugfs - Refactor DCCG into component folder - Refactor input mode programming for DIG FIFO - Reset DSC clock in post unlock update - Clean-up recout calculation for visual confirm - Enable urgent latency adjustments for DCN35 Acked-by: Tom Chung Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 235e43e10799..8698db8f3e45 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,7 +55,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.283" +#define DC_VER "3.2.284" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 7662bc61c030edae9346dc56daa6109ce353f5b4 Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Thu, 28 Mar 2024 13:43:36 -0400 Subject: drm/amd/display: Disable AC/DC codepath when unnecessary [WHY] If there are no DC clock limits present, or if the DC limits are the same as the AC limits, we can disable the AC/DC codepath as there won't be any validation differences between the two modes. [HOW] When all DC power mode clock limits are the same as the max clock values, there won't be any difference between AC mode and DC mode. Zero out DC limits that equal max and provide a new cap to indicate the presence of any non-zero DC mode limit. In summary: - zero out DC limits that are the same as max clock value - new dc cap to indicate the presence of DC mode limits - set limits present if any clock has distinct AC and DC values from SMU Acked-by: Alex Hung Reviewed-by: Rodrigo Siqueira Signed-off-by: Joshua Aberback Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c | 28 ++++++++++++++++------ drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 12 +++++++++- 3 files changed, 33 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') 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 1cf750cfed66..bd74ff47fb37 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 @@ -180,7 +180,6 @@ static void dcn401_build_wm_range_table(struct clk_mgr *clk_mgr) void dcn401_init_clocks(struct clk_mgr *clk_mgr_base) { struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); - unsigned int num_levels; struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk; unsigned int i; @@ -208,34 +207,43 @@ void dcn401_init_clocks(struct clk_mgr *clk_mgr_base) &clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz, &num_entries_per_clk->num_dcfclk_levels); clk_mgr_base->bw_params->dc_mode_limit.dcfclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DCFCLK); + if (num_entries_per_clk->num_dcfclk_levels && clk_mgr_base->bw_params->dc_mode_limit.dcfclk_mhz == + clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_dcfclk_levels - 1].dcfclk_mhz) + clk_mgr_base->bw_params->dc_mode_limit.dcfclk_mhz = 0; /* SOCCLK */ dcn401_init_single_clock(clk_mgr, PPCLK_SOCCLK, &clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz, &num_entries_per_clk->num_socclk_levels); clk_mgr_base->bw_params->dc_mode_limit.socclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_SOCCLK); + if (num_entries_per_clk->num_socclk_levels && clk_mgr_base->bw_params->dc_mode_limit.socclk_mhz == + clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_socclk_levels - 1].socclk_mhz) + clk_mgr_base->bw_params->dc_mode_limit.socclk_mhz = 0; /* DTBCLK */ if (!clk_mgr->base.ctx->dc->debug.disable_dtb_ref_clk_switch) { dcn401_init_single_clock(clk_mgr, PPCLK_DTBCLK, &clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz, &num_entries_per_clk->num_dtbclk_levels); - clk_mgr_base->bw_params->dc_mode_limit.dtbclk_mhz = - dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DTBCLK); + clk_mgr_base->bw_params->dc_mode_limit.dtbclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DTBCLK); + if (num_entries_per_clk->num_dtbclk_levels && clk_mgr_base->bw_params->dc_mode_limit.dtbclk_mhz == + clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_dtbclk_levels - 1].dtbclk_mhz) + clk_mgr_base->bw_params->dc_mode_limit.dtbclk_mhz = 0; } /* DISPCLK */ dcn401_init_single_clock(clk_mgr, PPCLK_DISPCLK, &clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz, &num_entries_per_clk->num_dispclk_levels); - num_levels = num_entries_per_clk->num_dispclk_levels; clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DISPCLK); + if (num_entries_per_clk->num_dispclk_levels && clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz == + clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_dispclk_levels - 1].dispclk_mhz) + clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz = 0; /* DPPCLK */ dcn401_init_single_clock(clk_mgr, PPCLK_DPPCLK, &clk_mgr_base->bw_params->clk_table.entries[0].dppclk_mhz, &num_entries_per_clk->num_dppclk_levels); - num_levels = num_entries_per_clk->num_dppclk_levels; if (num_entries_per_clk->num_dcfclk_levels && num_entries_per_clk->num_dtbclk_levels && @@ -243,7 +251,7 @@ void dcn401_init_clocks(struct clk_mgr *clk_mgr_base) clk_mgr->dpm_present = true; if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) { - for (i = 0; i < num_levels; i++) + for (i = 0; i < num_entries_per_clk->num_dispclk_levels; i++) if (clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz < khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_disp_clk_khz)) clk_mgr_base->bw_params->clk_table.entries[i].dispclk_mhz @@ -251,7 +259,7 @@ void dcn401_init_clocks(struct clk_mgr *clk_mgr_base) } if (clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz) { - for (i = 0; i < num_levels; i++) + for (i = 0; i < num_entries_per_clk->num_dppclk_levels; i++) if (clk_mgr_base->bw_params->clk_table.entries[i].dppclk_mhz < khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz)) clk_mgr_base->bw_params->clk_table.entries[i].dppclk_mhz @@ -842,12 +850,18 @@ static void dcn401_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base) } clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_UCLK); + if (num_entries_per_clk->num_memclk_levels && clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz == + clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_memclk_levels - 1].memclk_mhz) + clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz = 0; clk_mgr_base->bw_params->dc_mode_softmax_memclk = clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz; dcn401_init_single_clock(clk_mgr, PPCLK_FCLK, &clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz, &num_entries_per_clk->num_fclk_levels); clk_mgr_base->bw_params->dc_mode_limit.fclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_FCLK); + if (num_entries_per_clk->num_fclk_levels && clk_mgr_base->bw_params->dc_mode_limit.fclk_mhz == + clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_fclk_levels - 1].fclk_mhz) + clk_mgr_base->bw_params->dc_mode_limit.fclk_mhz = 0; if (num_entries_per_clk->num_memclk_levels >= num_entries_per_clk->num_fclk_levels) { num_levels = num_entries_per_clk->num_memclk_levels; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8698db8f3e45..2fce8c0303fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -290,6 +290,7 @@ struct dc_caps { uint32_t max_disp_clock_khz_at_vmin; uint8_t subvp_drr_vblank_start_margin_us; bool cursor_not_scaled; + bool dcmode_power_limits_present; }; struct dc_bug_wa { 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 d9a3d6c2da1f..3b74c4a9c2a8 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 @@ -212,9 +212,19 @@ void dcn401_init_hw(struct dc *dc) uint32_t backlight = MAX_BACKLIGHT_LEVEL; uint32_t user_level = MAX_BACKLIGHT_LEVEL; - if (dc->clk_mgr && dc->clk_mgr->funcs->init_clocks) + if (dc->clk_mgr && 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->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels && dc->clk_mgr->bw_params->dc_mode_limit.dcfclk_mhz) || + (dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels && dc->clk_mgr->bw_params->dc_mode_limit.dispclk_mhz) || + (dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels && dc->clk_mgr->bw_params->dc_mode_limit.dtbclk_mhz) || + (dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_fclk_levels && dc->clk_mgr->bw_params->dc_mode_limit.fclk_mhz) || + (dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels && dc->clk_mgr->bw_params->dc_mode_limit.memclk_mhz) || + (dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_socclk_levels && dc->clk_mgr->bw_params->dc_mode_limit.socclk_mhz); + } + // Initialize the dccg if (res_pool->dccg->funcs->dccg_init) res_pool->dccg->funcs->dccg_init(res_pool->dccg); -- cgit From c49e44ede5cdfe650c2f769d8bd58cbe289e87cd Mon Sep 17 00:00:00 2001 From: Daniel Miess Date: Tue, 23 Apr 2024 15:45:59 -0400 Subject: drm/amd/display: Enable SYMCLK gating in DCCG [WHY & HOW] Enable root clock optimization for SYMCLK and only disable it when it's actively used. Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Daniel Miess Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c | 102 ++++++++++++--------- .../drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 45 ++++++++- .../drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h | 2 + .../gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c | 1 + .../drm/amd/display/dc/hwss/dcn351/dcn351_init.c | 1 + .../drm/amd/display/dc/hwss/hw_sequencer_private.h | 4 + drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h | 7 ++ 8 files changed, 115 insertions(+), 48 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2fce8c0303fa..eef2f357fe14 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -726,6 +726,7 @@ enum pg_hw_pipe_resources { PG_DPSTREAM, PG_HDMISTREAM, PG_PHYSYMCLK, + PG_SYMCLK, PG_HW_PIPE_RESOURCES_NUM_ELEMENT }; 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 1fc3aa2b507b..d3b27920e294 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 @@ -655,9 +655,61 @@ static void dccg35_disable_symclk32_se( } } +static void dccg35_set_symclk_root_clock_gating(struct dccg *dccg, uint32_t stream_enc_inst, + uint32_t link_enc_inst, bool enable) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + switch (stream_enc_inst) { + case 0: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 1: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 2: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 3: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 4: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + } + + switch (link_enc_inst) { + case 0: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 1: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 2: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 3: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 4: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + } +} + void dccg35_init(struct dccg *dccg) { - int otg_inst; + int otg_inst, phy_inst; /* 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. @@ -671,10 +723,9 @@ void dccg35_init(struct dccg *dccg) dccg31_set_symclk32_le_root_clock_gating(dccg, otg_inst, false); } -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) -// for (otg_inst = 0; otg_inst < 4; otg_inst++) -// dccg35_disable_symclk_se(dccg, otg_inst, otg_inst); - + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + for (phy_inst = 0; phy_inst < 5; phy_inst++) + dccg35_set_symclk_root_clock_gating(dccg, phy_inst, phy_inst, false); if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) for (otg_inst = 0; otg_inst < 4; otg_inst++) { @@ -798,32 +849,22 @@ static void dccg35_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, case 0: REG_UPDATE(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, 1); - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, 1); break; case 1: REG_UPDATE(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, 1); - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, 1); break; case 2: REG_UPDATE(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, 1); - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, 1); break; case 3: REG_UPDATE(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, 1); - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, 1); break; case 4: REG_UPDATE(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, 1); - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, 1); break; } @@ -832,36 +873,26 @@ static void dccg35_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, 1, SYMCLKA_FE_SRC_SEL, link_enc_inst); - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, 1); break; case 1: REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, 1, SYMCLKB_FE_SRC_SEL, link_enc_inst); - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, 1); break; case 2: REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, 1, SYMCLKC_FE_SRC_SEL, link_enc_inst); - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, 1); break; case 3: REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, 1, SYMCLKD_FE_SRC_SEL, link_enc_inst); - 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: REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_EN, 1, SYMCLKE_FE_SRC_SEL, link_enc_inst); - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, 1); break; } } @@ -922,36 +953,26 @@ static void dccg35_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, 0, SYMCLKA_FE_SRC_SEL, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, 0); break; case 1: REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, 0, SYMCLKB_FE_SRC_SEL, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, 0); break; case 2: REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, 0, SYMCLKC_FE_SRC_SEL, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, 0); break; case 3: REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, 0, SYMCLKD_FE_SRC_SEL, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, 0); break; case 4: REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_EN, 0, SYMCLKE_FE_SRC_SEL, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, 0); break; } @@ -964,32 +985,22 @@ static void dccg35_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst case 0: REG_UPDATE(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, 0); break; case 1: REG_UPDATE(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, 0); break; case 2: REG_UPDATE(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, 0); break; case 3: REG_UPDATE(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, 0); break; case 4: REG_UPDATE(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, 0); -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) -// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, 0); break; } } @@ -1022,6 +1033,7 @@ static const struct dccg_funcs dccg35_funcs = { .set_valid_pixel_rate = dccg35_set_valid_pixel_rate, .enable_symclk_se = dccg35_enable_symclk_se, .disable_symclk_se = dccg35_disable_symclk_se, + .set_symclk_root_clock_gating = dccg35_set_symclk_root_clock_gating, .set_dtbclk_p_src = dccg35_set_dtbclk_p_src, }; 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 6d40e93b5497..6d9ec802f1bb 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 @@ -519,6 +519,17 @@ void dcn35_physymclk_root_clock_control(struct dce_hwseq *hws, unsigned int phy_ } } +void dcn35_symclk_root_clock_control(struct dce_hwseq *hws, unsigned int enc_inst, bool clock_on) +{ + if (!hws->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + return; + + if (hws->ctx->dc->res_pool->dccg->funcs->set_symclk_root_clock_gating) { + hws->ctx->dc->res_pool->dccg->funcs->set_symclk_root_clock_gating( + hws->ctx->dc->res_pool->dccg, enc_inst, enc_inst, clock_on); + } +} + void dcn35_dsc_pg_control( struct dce_hwseq *hws, unsigned int dsc_inst, @@ -1008,6 +1019,7 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, int i = 0, j = 0; int edp_num = 0; struct dc_link *edp_links[MAX_NUM_EDP] = { NULL }; + bool stream_enc_in_use[MAX_PIPES] = { false }; memset(update_state, 0, sizeof(struct pg_block_update)); @@ -1053,10 +1065,17 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, 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->stream_res.stream_enc && + !pipe_ctx->stream_res.hpo_dp_stream_enc) + stream_enc_in_use[pipe_ctx->stream_res.stream_enc->stream_enc_inst] = true; } + for (i = 0; i < dc->res_pool->pipe_count; i++) + if (stream_enc_in_use[i]) + update_state->pg_pipe_res_update[PG_SYMCLK][i] = 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; } @@ -1120,6 +1139,10 @@ void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, 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; + + if (j == PG_SYMCLK && new_pipe->stream_res.stream_enc && + !new_pipe->stream_res.hpo_dp_stream_enc) + update_state->pg_pipe_res_update[j][new_pipe->stream_res.stream_enc->stream_enc_inst] = true; } } else if (cur_pipe->plane_state == new_pipe->plane_state || cur_pipe == new_pipe) { @@ -1154,6 +1177,12 @@ void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, 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; + + if (j == PG_SYMCLK && + new_pipe->stream_res.stream_enc && + cur_pipe->stream_res.stream_enc != new_pipe->stream_res.stream_enc && + !new_pipe->stream_res.hpo_dp_stream_enc) + update_state->pg_pipe_res_update[j][new_pipe->stream_res.stream_enc->stream_enc_inst] = true; } } } @@ -1312,11 +1341,16 @@ void dcn35_root_clock_control(struct dc *dc, dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on); } - for (i = 0; i < dc->res_pool->dig_link_enc_count; i++) + 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); + if (update_state->pg_pipe_res_update[PG_SYMCLK][i]) + if (dc->hwseq->funcs.symclk_root_clock_control) + dc->hwseq->funcs.symclk_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]) { @@ -1342,11 +1376,16 @@ void dcn35_root_clock_control(struct dc *dc, dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on); } - for (i = 0; i < dc->res_pool->dig_link_enc_count; i++) + 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); + if (update_state->pg_pipe_res_update[PG_SYMCLK][i]) + if (dc->hwseq->funcs.symclk_root_clock_control) + dc->hwseq->funcs.symclk_root_clock_control(dc->hwseq, i, power_on); + } + } } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h index bc05beba5f2c..503a8419bae7 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h @@ -41,6 +41,8 @@ void dcn35_dpstream_root_clock_control(struct dce_hwseq *hws, unsigned int dp_hp void dcn35_physymclk_root_clock_control(struct dce_hwseq *hws, unsigned int phy_inst, bool clock_on); +void dcn35_symclk_root_clock_control(struct dce_hwseq *hws, unsigned int enc_inst, bool clock_on); + void dcn35_enable_power_gating_plane(struct dce_hwseq *hws, bool enable); void dcn35_set_dmu_fgcg(struct dce_hwseq *hws, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c index 663bacd1fafd..0b6d7d76c85b 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c @@ -150,6 +150,7 @@ static const struct hwseq_private_funcs dcn35_private_funcs = { .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, + .symclk_root_clock_control = dcn35_symclk_root_clock_control, .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, .update_odm = dcn35_update_odm, .set_hdr_multiplier = dcn10_set_hdr_multiplier, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c index d8de1c6a84e8..e8643f305fd6 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c @@ -149,6 +149,7 @@ static const struct hwseq_private_funcs dcn351_private_funcs = { .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, + .symclk_root_clock_control = dcn35_symclk_root_clock_control, .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, .update_odm = dcn35_update_odm, .set_hdr_multiplier = dcn10_set_hdr_multiplier, 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 7ac3f2a09487..e2189795ca30 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 @@ -128,6 +128,10 @@ struct hwseq_private_funcs { struct dce_hwseq *hws, unsigned int phy_inst, bool clock_on); + void (*symclk_root_clock_control)( + struct dce_hwseq *hws, + unsigned int enc_inst, + bool clock_on); void (*dpp_pg_control)(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h index 867bc67aabfa..5b0924ea78af 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h @@ -199,6 +199,13 @@ struct dccg_funcs { struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst); + + void (*set_symclk_root_clock_gating)( + struct dccg *dccg, + uint32_t stream_enc_inst, + uint32_t link_enc_inst, + bool enable); + void (*set_dp_dto)( struct dccg *dccg, const struct dp_dto_params *params); -- cgit From 2eb7d4b98700fe7612521e5226437fb9e7a65af5 Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Tue, 26 Mar 2024 18:44:34 -0400 Subject: drm/amd/display: Refactor dcn401_update_clocks [WHY & HOW] Refactor complex code into manageable functions. This also cleans up some updating logics. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: Dillon Varone Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/clk_mgr/dcn401/dalsmc.h | 8 +- .../amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c | 523 ++++++++++++++++++++- .../amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h | 94 ++++ .../dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.c | 80 +++- .../dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.h | 10 + drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +- drivers/gpu/drm/amd/display/dc/dc.h | 3 + drivers/gpu/drm/amd/display/include/dal_asic_id.h | 3 + 8 files changed, 718 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dalsmc.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dalsmc.h index 0d2584437934..5653c7991c62 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dalsmc.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dalsmc.h @@ -36,7 +36,13 @@ #define DALSMC_MSG_SetFclkSwitchAllow 0x11 #define DALSMC_MSG_SetCabForUclkPstate 0x12 #define DALSMC_MSG_SetWorstCaseUclkLatency 0x13 -#define DALSMC_Message_Count 0x14 +#define DALSMC_MSG_DcnExitReset 0x14 +#define DALSMC_MSG_ReturnHardMinStatus 0x15 +#define DALSMC_MSG_SetAlwaysWaitDmcubResp 0x16 +#define DALSMC_MSG_IndicateDrrStatus 0x17 // PMFW 15811 +#define DALSMC_MSG_ActiveUclkFclk 0x18 +#define DALSMC_MSG_IdleUclkFclk 0x19 +#define DALSMC_Message_Count 0x1A typedef enum { FCLK_SWITCH_DISALLOW, 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 bd74ff47fb37..d2abc00a60c5 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 @@ -67,6 +67,9 @@ static const struct clk_mgr_mask clk_mgr_mask_dcn401 = { CLK_COMMON_MASK_SH_LIST_DCN401(_MASK) }; +#define TO_DCN401_CLK_MGR(clk_mgr)\ + container_of(clk_mgr, struct dcn401_clk_mgr, base) + static bool dcn401_is_ppclk_dpm_enabled(struct clk_mgr_internal *clk_mgr, PPCLK_e clk) { bool ppclk_dpm_enabled = false; @@ -112,6 +115,30 @@ static bool dcn401_is_ppclk_dpm_enabled(struct clk_mgr_internal *clk_mgr, PPCLK_ return ppclk_dpm_enabled; } +static bool dcn401_is_ppclk_idle_dpm_enabled(struct clk_mgr_internal *clk_mgr, PPCLK_e clk) +{ + bool ppclk_idle_dpm_enabled = false; + + switch (clk) { + case PPCLK_UCLK: + case PPCLK_FCLK: + if (ASICREV_IS_GC_12_0_0_A0(clk_mgr->base.ctx->asic_id.hw_internal_rev) && + clk_mgr->smu_ver >= 0x681800) { + ppclk_idle_dpm_enabled = true; + } else if (ASICREV_IS_GC_12_0_1_A0(clk_mgr->base.ctx->asic_id.hw_internal_rev) && + clk_mgr->smu_ver >= 0x661300) { + ppclk_idle_dpm_enabled = true; + } + break; + default: + ppclk_idle_dpm_enabled = false; + } + + ppclk_idle_dpm_enabled &= clk_mgr->smu_present; + + return ppclk_idle_dpm_enabled; +} + /* Query SMU for all clock states for a particular clock */ static void dcn401_init_single_clock(struct clk_mgr_internal *clk_mgr, PPCLK_e clk, unsigned int *entry_0, unsigned int *num_levels) @@ -470,7 +497,7 @@ static void dcn401_update_clocks_update_dentist( } -static void dcn401_update_clocks(struct clk_mgr *clk_mgr_base, +static void dcn401_update_clocks_legacy(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool safe_to_lower) { @@ -512,7 +539,7 @@ static void dcn401_update_clocks(struct clk_mgr *clk_mgr_base, if (clk_mgr->smu_present) { if (enter_display_off == safe_to_lower) - dcn30_smu_set_num_of_displays(clk_mgr, display_count); + dcn401_smu_set_num_of_displays(clk_mgr, display_count); clk_mgr_base->clks.fclk_prev_p_state_change_support = clk_mgr_base->clks.fclk_p_state_change_support; @@ -542,7 +569,7 @@ static void dcn401_update_clocks(struct clk_mgr *clk_mgr_base, 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; if (dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_DCFCLK)) - dcn30_smu_set_min_deep_sleep_dcef_clk(clk_mgr, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_deep_sleep_khz)); + dcn401_smu_set_min_deep_sleep_dcef_clk(clk_mgr, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_deep_sleep_khz)); } if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr_base->clks.socclk_khz)) @@ -668,6 +695,496 @@ static void dcn401_update_clocks(struct clk_mgr *clk_mgr_base, clk_mgr_base->clks.dispclk_khz / 1000 / 7); } +static void dcn401_build_update_clocks_sequence( + struct clk_mgr *clk_mgr_base, + struct dc_state *context, + bool safe_to_lower, + unsigned int *num_steps) +{ + struct clk_mgr_internal *clk_mgr_internal = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct dcn401_clk_mgr *clk_mgr401 = TO_DCN401_CLK_MGR(clk_mgr_internal); + struct dc *dc = clk_mgr_base->ctx->dc; + struct dmcu *dmcu = clk_mgr_base->ctx->dc->res_pool->dmcu; + struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; + struct dcn401_clk_mgr_block_sequence *block_sequence = clk_mgr401->block_sequence; + bool force_reset = false; + bool enter_display_off = false; + bool update_active_fclk = false; + bool update_active_uclk = false; + bool update_idle_fclk = false; + bool update_idle_uclk = false; + bool update_dispclk = false; + bool update_dppclk = false; + bool dppclk_lowered = false; + bool is_idle_dpm_enabled = dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_UCLK) && + dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_FCLK) && + dcn401_is_ppclk_idle_dpm_enabled(clk_mgr_internal, PPCLK_UCLK) && + dcn401_is_ppclk_idle_dpm_enabled(clk_mgr_internal, PPCLK_FCLK); + int total_plane_count = clk_mgr_helper_get_active_plane_cnt(dc, context); + int active_uclk_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz); + int active_fclk_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.fclk_khz); + int idle_uclk_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.idle_dramclk_khz); + int idle_fclk_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.idle_fclk_khz); + + int display_count; + bool fclk_p_state_change_support, uclk_p_state_change_support; + + *num_steps = 0; + + /* CLK_MGR401_READ_CLOCKS_FROM_DENTIST */ + if (clk_mgr_base->clks.dispclk_khz == 0 || + (dc->debug.force_clock_mode & 0x1)) { + /* This is from resume or boot up, if forced_clock cfg option used, + * we bypass program dispclk and DPPCLK, but need set them for S3. + * Force_clock_mode 0x1: force reset the clock even it is the same clock + * as long as it is in Passive level. + */ + force_reset = true; + + block_sequence[*num_steps].func = CLK_MGR401_READ_CLOCKS_FROM_DENTIST; + (*num_steps)++; + } + + /* CLK_MGR401_UPDATE_NUM_DISPLAYS */ + if (clk_mgr_internal->smu_present) { + display_count = clk_mgr_helper_get_active_display_cnt(dc, context); + + if (display_count == 0) + enter_display_off = true; + + if (enter_display_off == safe_to_lower) { + block_sequence[*num_steps].params.update_num_displays_params.num_displays = display_count; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_NUM_DISPLAYS; + (*num_steps)++; + } + } + + /* CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT */ + clk_mgr_base->clks.fclk_prev_p_state_change_support = clk_mgr_base->clks.fclk_p_state_change_support; + fclk_p_state_change_support = new_clocks->fclk_p_state_change_support || (total_plane_count == 0); + if (should_update_pstate_support(safe_to_lower, fclk_p_state_change_support, clk_mgr_base->clks.fclk_p_state_change_support)) { + clk_mgr_base->clks.fclk_p_state_change_support = fclk_p_state_change_support; + update_active_fclk = true; + update_idle_fclk = true; + + /* To enable FCLK P-state switching, send FCLK_PSTATE_SUPPORTED message to PMFW */ + if (clk_mgr_base->clks.fclk_p_state_change_support) { + /* Handle the code for sending a message to PMFW that FCLK P-state change is supported */ + if (dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_FCLK)) { + block_sequence[*num_steps].params.update_fclk_pstate_support_params.support = FCLK_PSTATE_SUPPORTED; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT; + (*num_steps)++; + } + } else { + /* P-State is not supported so force max clocks */ + idle_fclk_mhz = + clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_fclk_levels - 1].fclk_mhz; + active_fclk_mhz = idle_fclk_mhz; + } + } + + /* UPDATE DCFCLK */ + 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; + if (dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_DCFCLK)) { + block_sequence[*num_steps].params.update_hardmin_params.ppclk = PPCLK_DCFCLK; + block_sequence[*num_steps].params.update_hardmin_params.freq_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_khz); + block_sequence[*num_steps].params.update_hardmin_params.response = NULL; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_HARDMIN_PPCLK; + (*num_steps)++; + } + } + + /* CLK_MGR401_UPDATE_DEEP_SLEEP_DCFCLK */ + 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; + if (dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_DCFCLK)) { + block_sequence[*num_steps].params.update_deep_sleep_dcfclk_params.freq_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_deep_sleep_khz); + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_DEEP_SLEEP_DCFCLK; + (*num_steps)++; + } + } + + /* SOCCLK */ + if (should_set_clock(safe_to_lower, new_clocks->socclk_khz, clk_mgr_base->clks.socclk_khz)) + /* We don't actually care about socclk, don't notify SMU of hard min */ + clk_mgr_base->clks.socclk_khz = new_clocks->socclk_khz; + + /* CLK_MGR401_UPDATE_CAB_FOR_UCLK */ + clk_mgr_base->clks.prev_p_state_change_support = clk_mgr_base->clks.p_state_change_support; + clk_mgr_base->clks.prev_num_ways = clk_mgr_base->clks.num_ways; + + if (clk_mgr_base->clks.num_ways != new_clocks->num_ways && + clk_mgr_base->clks.num_ways < new_clocks->num_ways) { + clk_mgr_base->clks.num_ways = new_clocks->num_ways; + if (dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_UCLK)) { + block_sequence[*num_steps].params.update_cab_for_uclk_params.num_ways = clk_mgr_base->clks.num_ways; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_CAB_FOR_UCLK; + (*num_steps)++; + } + } + + /* UCLK */ + uclk_p_state_change_support = new_clocks->p_state_change_support || (total_plane_count == 0); + if (should_update_pstate_support(safe_to_lower, uclk_p_state_change_support, clk_mgr_base->clks.p_state_change_support)) { + clk_mgr_base->clks.p_state_change_support = uclk_p_state_change_support; + update_active_uclk = true; + update_idle_uclk = true; + + /* to disable P-State switching, set UCLK min = max */ + if (!clk_mgr_base->clks.p_state_change_support) { + if (dc->clk_mgr->dc_mode_softmax_enabled) { + /* will never have the functional UCLK min above the softmax + * since we calculate mode support based on softmax being the max UCLK + * frequency. + */ + active_uclk_mhz = clk_mgr_base->bw_params->dc_mode_softmax_memclk; + } else { + active_uclk_mhz = clk_mgr_base->bw_params->max_memclk_mhz; + } + idle_uclk_mhz = active_uclk_mhz; + } + } + + /* Always update saved value, even if new value not set due to P-State switching unsupported */ + if (should_set_clock(safe_to_lower, new_clocks->dramclk_khz, clk_mgr_base->clks.dramclk_khz)) { + clk_mgr_base->clks.dramclk_khz = new_clocks->dramclk_khz; + + if (clk_mgr_base->clks.p_state_change_support) { + update_active_uclk = true; + active_uclk_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz); + } + } + if (should_set_clock(safe_to_lower, new_clocks->idle_dramclk_khz, clk_mgr_base->clks.idle_dramclk_khz)) { + clk_mgr_base->clks.idle_dramclk_khz = new_clocks->idle_dramclk_khz; + + if (clk_mgr_base->clks.p_state_change_support) { + update_idle_uclk = true; + idle_uclk_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.idle_dramclk_khz); + } + } + + /* set UCLK to requested value */ + if ((update_active_uclk || update_idle_uclk) && + dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_UCLK) && + !is_idle_dpm_enabled) { + block_sequence[*num_steps].params.update_hardmin_params.ppclk = PPCLK_UCLK; + block_sequence[*num_steps].params.update_hardmin_params.freq_mhz = active_uclk_mhz; + block_sequence[*num_steps].params.update_hardmin_params.response = NULL; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_HARDMIN_PPCLK; + (*num_steps)++; + } + + /* FCLK */ + /* Always update saved value, even if new value not set due to P-State switching unsupported */ + if (should_set_clock(safe_to_lower, new_clocks->fclk_khz, clk_mgr_base->clks.fclk_khz)) { + clk_mgr_base->clks.fclk_khz = new_clocks->fclk_khz; + + if (clk_mgr_base->clks.fclk_p_state_change_support) { + update_active_fclk = true; + active_fclk_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.fclk_khz); + } + } + + if (should_set_clock(safe_to_lower, new_clocks->idle_fclk_khz, clk_mgr_base->clks.idle_fclk_khz)) { + clk_mgr_base->clks.idle_fclk_khz = new_clocks->idle_fclk_khz; + + if (clk_mgr_base->clks.fclk_p_state_change_support) { + update_idle_fclk = true; + idle_fclk_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.idle_fclk_khz); + } + } + + /* When idle DPM is enabled, need to send active and idle hardmins separately */ + /* CLK_MGR401_UPDATE_ACTIVE_HARDMINS */ + if ((update_active_uclk || update_active_fclk) && is_idle_dpm_enabled) { + block_sequence[*num_steps].params.update_idle_hardmin_params.uclk_mhz = active_uclk_mhz; + block_sequence[*num_steps].params.update_idle_hardmin_params.fclk_mhz = active_fclk_mhz; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_ACTIVE_HARDMINS; + (*num_steps)++; + } + + /* CLK_MGR401_UPDATE_IDLE_HARDMINS */ + if ((update_idle_uclk || update_idle_uclk) && is_idle_dpm_enabled) { + block_sequence[*num_steps].params.update_idle_hardmin_params.uclk_mhz = idle_uclk_mhz; + block_sequence[*num_steps].params.update_idle_hardmin_params.fclk_mhz = idle_fclk_mhz; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_IDLE_HARDMINS; + (*num_steps)++; + } + + /* CLK_MGR401_UPDATE_WAIT_FOR_DMUB_ACK, CLK_MGR401_INDICATE_DRR_STATUS*/ + if (clk_mgr_base->clks.fw_based_mclk_switching != new_clocks->fw_based_mclk_switching) { + clk_mgr_base->clks.fw_based_mclk_switching = new_clocks->fw_based_mclk_switching; + + block_sequence[*num_steps].params.update_wait_for_dmub_ack_params.enable = clk_mgr_base->clks.fw_based_mclk_switching; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_WAIT_FOR_DMUB_ACK; + (*num_steps)++; + + block_sequence[*num_steps].params.indicate_drr_status_params.mod_drr_for_pstate = clk_mgr_base->clks.fw_based_mclk_switching; + block_sequence[*num_steps].func = CLK_MGR401_INDICATE_DRR_STATUS; + (*num_steps)++; + } + + /* set FCLK to requested value if P-State switching is supported, or to re-enable P-State switching */ + if ((update_active_fclk || update_idle_fclk)) { + /* disable FCLK P-State support if needed */ + if (clk_mgr_base->clks.fclk_p_state_change_support != clk_mgr_base->clks.fclk_prev_p_state_change_support && + dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_FCLK)) { + block_sequence[*num_steps].params.update_fclk_pstate_support_params.support = FCLK_PSTATE_NOTSUPPORTED; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT; + (*num_steps)++; + } + + /* No need to send active FCLK hardmin, automatically set based on DCFCLK */ + // block_sequence[*num_steps].update_hardmin_params.clk_mgr = clk_mgr; + // block_sequence[*num_steps].update_hardmin_params.ppclk = PPCLK_FCLK; + // block_sequence[*num_steps].update_hardmin_params.freq_mhz = active_fclk_mhz; + // block_sequence[*num_steps].update_hardmin_params.response = NULL; + // block_sequence[*num_steps].func = CLK_MGR401_UPDATE_HARDMIN_PPCLK; + // (*num_steps)++; + } + + /* CLK_MGR401_UPDATE_CAB_FOR_UCLK */ + if (clk_mgr_base->clks.num_ways != new_clocks->num_ways && + clk_mgr_base->clks.num_ways > new_clocks->num_ways) { + clk_mgr_base->clks.num_ways = new_clocks->num_ways; + if (dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_UCLK)) { + block_sequence[*num_steps].params.update_cab_for_uclk_params.num_ways = clk_mgr_base->clks.num_ways; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_CAB_FOR_UCLK; + (*num_steps)++; + } + } + + /* DTBCLK */ + if (!new_clocks->dtbclk_en && dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_DTBCLK)) + new_clocks->ref_dtbclk_khz = clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz * 1000; + + /* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */ + if (!dc->debug.disable_dtb_ref_clk_switch && + should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000, clk_mgr_base->clks.ref_dtbclk_khz / 1000) && //TODO these should be ceiled + dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_DTBCLK)) { + /* DCCG requires KHz precision for DTBCLK */ + block_sequence[*num_steps].params.update_hardmin_params.ppclk = PPCLK_DTBCLK; + block_sequence[*num_steps].params.update_hardmin_params.freq_mhz = khz_to_mhz_ceil(new_clocks->ref_dtbclk_khz); + block_sequence[*num_steps].params.update_hardmin_params.response = &clk_mgr_base->clks.ref_dtbclk_khz; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_HARDMIN_PPCLK; + (*num_steps)++; + + /* Update DTO in DCCG */ + block_sequence[*num_steps].params.update_dtbclk_dto_params.context = context; + block_sequence[*num_steps].params.update_dtbclk_dto_params.ref_dtbclk_khz = clk_mgr_base->clks.ref_dtbclk_khz; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_DTBCLK_DTO; + (*num_steps)++; + } + + 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) + dppclk_lowered = true; + + clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz; + clk_mgr_base->clks.actual_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)) { + clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; + + update_dispclk = true; + } + + if (dc->config.forced_clocks == false || (force_reset && safe_to_lower)) { + if (dppclk_lowered) { + /* if clock is being lowered, increase DTO before lowering refclk */ + block_sequence[*num_steps].params.update_dppclk_dto_params.context = context; + block_sequence[*num_steps].params.update_dppclk_dto_params.dppclk_khz = clk_mgr_base->clks.dppclk_khz; + block_sequence[*num_steps].params.update_dppclk_dto_params.safe_to_lower = safe_to_lower; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_DPPCLK_DTO; + (*num_steps)++; + + block_sequence[*num_steps].params.update_dentist_params.context = context; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_DENTIST; + (*num_steps)++; + + if (dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_DPPCLK)) { + block_sequence[*num_steps].params.update_hardmin_optimized_params.ppclk = PPCLK_DPPCLK; + block_sequence[*num_steps].params.update_hardmin_optimized_params.freq_khz = clk_mgr_base->clks.dppclk_khz; + block_sequence[*num_steps].params.update_hardmin_optimized_params.response = &clk_mgr_base->clks.actual_dppclk_khz; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_HARDMIN_PPCLK_OPTIMIZED; + (*num_steps)++; + + block_sequence[*num_steps].params.update_dppclk_dto_params.context = context; + block_sequence[*num_steps].params.update_dppclk_dto_params.dppclk_khz = clk_mgr_base->clks.actual_dppclk_khz; + block_sequence[*num_steps].params.update_dppclk_dto_params.safe_to_lower = safe_to_lower; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_DPPCLK_DTO; + (*num_steps)++; + } + } else { + /* if clock is being raised, increase refclk before lowering DTO */ + if (update_dppclk && dcn401_is_ppclk_dpm_enabled(clk_mgr_internal, PPCLK_DPPCLK)) { + block_sequence[*num_steps].params.update_hardmin_optimized_params.ppclk = PPCLK_DPPCLK; + block_sequence[*num_steps].params.update_hardmin_optimized_params.freq_khz = clk_mgr_base->clks.dppclk_khz; + block_sequence[*num_steps].params.update_hardmin_optimized_params.response = &clk_mgr_base->clks.actual_dppclk_khz; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_HARDMIN_PPCLK_OPTIMIZED; + (*num_steps)++; + } + + if (update_dppclk || update_dispclk) { + block_sequence[*num_steps].params.update_dentist_params.context = context; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_DENTIST; + (*num_steps)++; + } + + block_sequence[*num_steps].params.update_dppclk_dto_params.context = context; + block_sequence[*num_steps].params.update_dppclk_dto_params.dppclk_khz = clk_mgr_base->clks.actual_dppclk_khz; + block_sequence[*num_steps].params.update_dppclk_dto_params.safe_to_lower = safe_to_lower; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_DPPCLK_DTO; + (*num_steps)++; + } + } + + if (update_dispclk && dmcu && dmcu->funcs->is_dmcu_initialized(dmcu)) { + /*update dmcu for wait_loop count*/ + block_sequence[*num_steps].params.update_psr_wait_loop_params.dmcu = dmcu; + block_sequence[*num_steps].params.update_psr_wait_loop_params.wait = clk_mgr_base->clks.dispclk_khz / 1000 / 7; + block_sequence[*num_steps].func = CLK_MGR401_UPDATE_PSR_WAIT_LOOP; + (*num_steps)++; + } +} + +static void dcn401_update_clocks(struct clk_mgr *clk_mgr_base, + struct dc_state *context, + bool safe_to_lower) +{ + struct clk_mgr_internal *clk_mgr_internal = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct dcn401_clk_mgr *clk_mgr401 = TO_DCN401_CLK_MGR(clk_mgr_internal); + struct dc *dc = clk_mgr_base->ctx->dc; + + unsigned int num_steps = 0; + + unsigned int i; + union dcn401_clk_mgr_block_sequence_params *params; + + if (dc->work_arounds.skip_clock_update) + return; + + if (dc->debug.enable_legacy_clock_update) { + dcn401_update_clocks_legacy(clk_mgr_base, context, safe_to_lower); + return; + } + + /* build clock update sequence */ + dcn401_build_update_clocks_sequence(clk_mgr_base, + context, + safe_to_lower, + &num_steps); + + /* execute sequence */ + for (i = 0; i < num_steps; i++) { + params = &clk_mgr401->block_sequence[i].params; + + switch (clk_mgr401->block_sequence[i].func) { + case CLK_MGR401_READ_CLOCKS_FROM_DENTIST: + dcn2_read_clocks_from_hw_dentist(clk_mgr_base); + break; + case CLK_MGR401_UPDATE_NUM_DISPLAYS: + dcn401_smu_set_num_of_displays(clk_mgr_internal, + params->update_num_displays_params.num_displays); + break; + case CLK_MGR401_UPDATE_HARDMIN_PPCLK: + if (params->update_hardmin_params.response) + *params->update_hardmin_params.response = dcn401_smu_set_hard_min_by_freq( + clk_mgr_internal, + params->update_hardmin_params.ppclk, + params->update_hardmin_params.freq_mhz); + else + dcn401_smu_set_hard_min_by_freq(clk_mgr_internal, + params->update_hardmin_params.ppclk, + params->update_hardmin_params.freq_mhz); + break; + case CLK_MGR401_UPDATE_HARDMIN_PPCLK_OPTIMIZED: + if (params->update_hardmin_optimized_params.response) + *params->update_hardmin_optimized_params.response = dcn401_set_hard_min_by_freq_optimized( + clk_mgr_internal, + params->update_hardmin_optimized_params.ppclk, + params->update_hardmin_optimized_params.freq_khz); + else + dcn401_set_hard_min_by_freq_optimized(clk_mgr_internal, + params->update_hardmin_optimized_params.ppclk, + params->update_hardmin_optimized_params.freq_khz); + break; + case CLK_MGR401_UPDATE_ACTIVE_HARDMINS: + dcn401_smu_set_active_uclk_fclk_hardmin( + clk_mgr_internal, + params->update_idle_hardmin_params.uclk_mhz, + params->update_idle_hardmin_params.fclk_mhz); + break; + case CLK_MGR401_UPDATE_IDLE_HARDMINS: + dcn401_smu_set_idle_uclk_fclk_hardmin( + clk_mgr_internal, + params->update_idle_hardmin_params.uclk_mhz, + params->update_idle_hardmin_params.fclk_mhz); + break; + case CLK_MGR401_UPDATE_DEEP_SLEEP_DCFCLK: + dcn401_smu_set_min_deep_sleep_dcef_clk( + clk_mgr_internal, + params->update_deep_sleep_dcfclk_params.freq_mhz); + break; + case CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT: + dcn401_smu_send_fclk_pstate_message( + clk_mgr_internal, + params->update_fclk_pstate_support_params.support); + break; + case CLK_MGR401_UPDATE_CAB_FOR_UCLK: + dcn401_smu_send_cab_for_uclk_message( + clk_mgr_internal, + params->update_cab_for_uclk_params.num_ways); + break; + case CLK_MGR401_UPDATE_WAIT_FOR_DMUB_ACK: + dcn401_smu_wait_for_dmub_ack_mclk( + clk_mgr_internal, + params->update_wait_for_dmub_ack_params.enable); + break; + case CLK_MGR401_INDICATE_DRR_STATUS: + dcn401_smu_indicate_drr_status( + clk_mgr_internal, + params->indicate_drr_status_params.mod_drr_for_pstate); + break; + case CLK_MGR401_UPDATE_DPPCLK_DTO: + dcn401_update_clocks_update_dpp_dto( + clk_mgr_internal, + params->update_dppclk_dto_params.context, + params->update_dppclk_dto_params.safe_to_lower, + params->update_dppclk_dto_params.dppclk_khz); + break; + case CLK_MGR401_UPDATE_DTBCLK_DTO: + dcn401_update_clocks_update_dtb_dto( + clk_mgr_internal, + params->update_dtbclk_dto_params.context, + params->update_dtbclk_dto_params.ref_dtbclk_khz); + break; + case CLK_MGR401_UPDATE_DENTIST: + dcn401_update_clocks_update_dentist( + clk_mgr_internal, + params->update_dentist_params.context); + break; + case CLK_MGR401_UPDATE_PSR_WAIT_LOOP: + params->update_psr_wait_loop_params.dmcu->funcs->set_psr_wait_loop( + params->update_psr_wait_loop_params.dmcu, + params->update_psr_wait_loop_params.wait); + break; + default: + /* this should never happen */ + BREAK_TO_DEBUGGER(); + break; + } + } +} + static uint32_t dcn401_get_vco_frequency_from_reg(struct clk_mgr_internal *clk_mgr) { struct fixed31_32 pll_req; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h index dad203de0dd4..e2a3fbb6c3c3 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h @@ -5,8 +5,102 @@ #ifndef __DCN401_CLK_MGR_H_ #define __DCN401_CLK_MGR_H_ +#define DCN401_CLK_MGR_MAX_SEQUENCE_SIZE 30 + +union dcn401_clk_mgr_block_sequence_params { + struct { + /* inputs */ + uint32_t num_displays; + } update_num_displays_params; + struct { + /* inputs */ + uint32_t ppclk; + uint16_t freq_mhz; + /* outputs */ + uint32_t *response; + } update_hardmin_params; + struct { + /* inputs */ + uint32_t ppclk; + int freq_khz; + /* outputs */ + uint32_t *response; + } update_hardmin_optimized_params; + struct { + /* inputs */ + uint16_t uclk_mhz; + uint16_t fclk_mhz; + } update_idle_hardmin_params; + struct { + /* inputs */ + uint16_t freq_mhz; + } update_deep_sleep_dcfclk_params; + struct { + /* inputs */ + bool support; + } update_fclk_pstate_support_params; + struct { + /* inputs */ + unsigned int num_ways; + } update_cab_for_uclk_params; + struct { + /* inputs */ + bool enable; + } update_wait_for_dmub_ack_params; + struct { + /* inputs */ + bool mod_drr_for_pstate; + } indicate_drr_status_params; + struct { + /* inputs */ + struct dc_state *context; + int dppclk_khz; + bool safe_to_lower; + } update_dppclk_dto_params; + struct { + /* inputs */ + struct dc_state *context; + int ref_dtbclk_khz; + } update_dtbclk_dto_params; + struct { + /* inputs */ + struct dc_state *context; + int ref_dtbclk_khz; + } update_dentist_params; + struct { + /* inputs */ + struct dmcu *dmcu; + unsigned int wait; + } update_psr_wait_loop_params; +}; + +enum dcn401_clk_mgr_block_sequence_func { + CLK_MGR401_READ_CLOCKS_FROM_DENTIST, + CLK_MGR401_UPDATE_NUM_DISPLAYS, + CLK_MGR401_UPDATE_HARDMIN_PPCLK, + CLK_MGR401_UPDATE_HARDMIN_PPCLK_OPTIMIZED, + CLK_MGR401_UPDATE_ACTIVE_HARDMINS, + CLK_MGR401_UPDATE_IDLE_HARDMINS, + CLK_MGR401_UPDATE_DEEP_SLEEP_DCFCLK, + CLK_MGR401_UPDATE_FCLK_PSTATE_SUPPORT, + CLK_MGR401_UPDATE_CAB_FOR_UCLK, + CLK_MGR401_UPDATE_WAIT_FOR_DMUB_ACK, + CLK_MGR401_INDICATE_DRR_STATUS, + CLK_MGR401_UPDATE_DPPCLK_DTO, + CLK_MGR401_UPDATE_DTBCLK_DTO, + CLK_MGR401_UPDATE_DENTIST, + CLK_MGR401_UPDATE_PSR_WAIT_LOOP, +}; + +struct dcn401_clk_mgr_block_sequence { + union dcn401_clk_mgr_block_sequence_params params; + enum dcn401_clk_mgr_block_sequence_func func; +}; + struct dcn401_clk_mgr { struct clk_mgr_internal base; + + struct dcn401_clk_mgr_block_sequence block_sequence[DCN401_CLK_MGR_MAX_SEQUENCE_SIZE]; }; void dcn401_init_clocks(struct clk_mgr *clk_mgr_base); diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.c index 054e8bd686f1..a3d0a48ed7ce 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.c @@ -105,6 +105,7 @@ void dcn401_smu_set_pme_workaround(struct clk_mgr_internal *clk_mgr) unsigned int dcn401_smu_set_hard_min_by_freq(struct clk_mgr_internal *clk_mgr, uint32_t clk, uint16_t freq_mhz) { uint32_t response = 0; + bool hard_min_done = false; /* bits 23:16 for clock type, lower 16 bits for frequency in MHz */ uint32_t param = (clk << 16) | freq_mhz; @@ -114,7 +115,84 @@ unsigned int dcn401_smu_set_hard_min_by_freq(struct clk_mgr_internal *clk_mgr, u dcn401_smu_send_msg_with_param(clk_mgr, DALSMC_MSG_SetHardMinByFreq, param, &response); - smu_print("SMU Frequency set = %d KHz\n", response); + /* wait until hardmin acknowledged */ + //hard_min_done = dcn401_smu_wait_get_hard_min_status(clk_mgr, clk); + smu_print("SMU Frequency set = %d KHz hard_min_done %d\n", response, hard_min_done); return response; } + +void dcn401_smu_wait_for_dmub_ack_mclk(struct clk_mgr_internal *clk_mgr, bool enable) +{ + smu_print("SMU to wait for DMCUB ack for MCLK : %d\n", enable); + + dcn401_smu_send_msg_with_param(clk_mgr, DALSMC_MSG_SetAlwaysWaitDmcubResp, enable ? 1 : 0, NULL); +} + +void dcn401_smu_indicate_drr_status(struct clk_mgr_internal *clk_mgr, bool mod_drr_for_pstate) +{ + smu_print("SMU Set indicate drr status = %d\n", mod_drr_for_pstate); + + dcn401_smu_send_msg_with_param(clk_mgr, + DALSMC_MSG_IndicateDrrStatus, mod_drr_for_pstate ? 1 : 0, NULL); +} + +bool dcn401_smu_set_idle_uclk_fclk_hardmin(struct clk_mgr_internal *clk_mgr, + uint16_t uclk_freq_mhz, + uint16_t fclk_freq_mhz) +{ + uint32_t response = 0; + bool success; + + /* 15:0 for uclk, 32:16 for fclk */ + uint32_t param = (fclk_freq_mhz << 16) | uclk_freq_mhz; + + smu_print("SMU Set idle hardmin by freq: uclk_freq_mhz = %d MHz, fclk_freq_mhz = %d MHz\n", uclk_freq_mhz, fclk_freq_mhz); + + success = dcn401_smu_send_msg_with_param(clk_mgr, + DALSMC_MSG_IdleUclkFclk, param, &response); + + /* wait until hardmin acknowledged */ + //success &= dcn401_smu_wait_get_hard_min_status(clk_mgr, PPCLK_UCLK); + smu_print("SMU hard_min_done %d\n", success); + + return success; +} + +bool dcn401_smu_set_active_uclk_fclk_hardmin(struct clk_mgr_internal *clk_mgr, + uint16_t uclk_freq_mhz, + uint16_t fclk_freq_mhz) +{ + uint32_t response = 0; + bool success; + + /* 15:0 for uclk, 32:16 for fclk */ + uint32_t param = (fclk_freq_mhz << 16) | uclk_freq_mhz; + + smu_print("SMU Set active hardmin by freq: uclk_freq_mhz = %d MHz, fclk_freq_mhz = %d MHz\n", uclk_freq_mhz, fclk_freq_mhz); + + success = dcn401_smu_send_msg_with_param(clk_mgr, + DALSMC_MSG_ActiveUclkFclk, param, &response); + + /* wait until hardmin acknowledged */ + //success &= dcn401_smu_wait_get_hard_min_status(clk_mgr, PPCLK_UCLK); + smu_print("SMU hard_min_done %d\n", success); + + return success; +} + +void dcn401_smu_set_min_deep_sleep_dcef_clk(struct clk_mgr_internal *clk_mgr, uint32_t freq_mhz) +{ + smu_print("SMU Set min deep sleep dcef clk: freq_mhz = %d MHz\n", freq_mhz); + + dcn401_smu_send_msg_with_param(clk_mgr, + DALSMC_MSG_SetMinDeepSleepDcfclk, freq_mhz, NULL); +} + +void dcn401_smu_set_num_of_displays(struct clk_mgr_internal *clk_mgr, uint32_t num_displays) +{ + smu_print("SMU Set num of displays: num_displays = %d\n", num_displays); + + dcn401_smu_send_msg_with_param(clk_mgr, + DALSMC_MSG_NumOfDisplays, num_displays, NULL); +} diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.h index 8918bc52c2af..892881d11ce8 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.h @@ -17,5 +17,15 @@ void dcn401_smu_send_cab_for_uclk_message(struct clk_mgr_internal *clk_mgr, unsi void dcn401_smu_transfer_wm_table_dram_2_smu(struct clk_mgr_internal *clk_mgr); void dcn401_smu_set_pme_workaround(struct clk_mgr_internal *clk_mgr); unsigned int dcn401_smu_set_hard_min_by_freq(struct clk_mgr_internal *clk_mgr, uint32_t clk, uint16_t freq_mhz); +void dcn401_smu_wait_for_dmub_ack_mclk(struct clk_mgr_internal *clk_mgr, bool enable); +void dcn401_smu_indicate_drr_status(struct clk_mgr_internal *clk_mgr, bool mod_drr_for_pstate); +bool dcn401_smu_set_idle_uclk_fclk_hardmin(struct clk_mgr_internal *clk_mgr, + uint16_t uclk_freq_mhz, + uint16_t fclk_freq_mhz); +bool dcn401_smu_set_active_uclk_fclk_hardmin(struct clk_mgr_internal *clk_mgr, + uint16_t uclk_freq_mhz, + uint16_t fclk_freq_mhz); +void dcn401_smu_set_min_deep_sleep_dcef_clk(struct clk_mgr_internal *clk_mgr, uint32_t freq_mhz); +void dcn401_smu_set_num_of_displays(struct clk_mgr_internal *clk_mgr, uint32_t num_displays); #endif /* __DCN401_CLK_MGR_SMU_MSG_H_ */ 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 fd624b1fee25..8a5cc8b80217 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -204,7 +204,8 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) dc_version = DCN_VERSION_3_51; break; case AMDGPU_FAMILY_GC_12_0_0: - if (ASICREV_IS_DCN401(asic_id.hw_internal_rev)) + if (ASICREV_IS_GC_12_0_1_A0(asic_id.hw_internal_rev) || + ASICREV_IS_GC_12_0_0_A0(asic_id.hw_internal_rev)) dc_version = DCN_VERSION_4_01; break; default: diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index eef2f357fe14..d550b6f97039 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -610,6 +610,8 @@ struct dc_clocks { int max_supported_dispclk_khz; int bw_dppclk_khz; /*a copy of dppclk_khz*/ int bw_dispclk_khz; + int idle_dramclk_khz; + int idle_fclk_khz; }; struct dc_bw_validation_profile { @@ -1035,6 +1037,7 @@ struct dc_debug_options { uint32_t dml21_force_pstate_method_value; uint32_t dml21_disable_pstate_method_mask; union dmub_fams2_global_feature_config fams2_config; + bool enable_legacy_clock_update; unsigned int force_cositing; }; 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 25333337461e..090230d29df8 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -266,6 +266,9 @@ enum { GC_12_UNKNOWN = 0xFF, }; +#define ASICREV_IS_GC_12_0_1_A0(eChipRev) (eChipRev >= GC_12_0_1_A0 && eChipRev < GC_12_0_0_A0) +#define ASICREV_IS_GC_12_0_0_A0(eChipRev) (eChipRev >= GC_12_0_0_A0 && eChipRev < 0xFF) + #define ASICREV_IS_DCN4(eChipRev) (eChipRev >= GC_12_0_1_A0 && eChipRev < GC_12_0_0_A0) #define ASICREV_IS_DCN401(eChipRev) (eChipRev >= GC_12_0_0_A0 && eChipRev < GC_12_UNKNOWN) -- cgit From f45957432351b58a77fab63989ca842c314847b4 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 5 May 2024 22:28:31 -0400 Subject: drm/amd/display: 3.2.285 This version brings along following fixes: - Read default boot options - Find max flickerless instant vtotal delta - Refactor dcn401_update_clocks - Reduce I2C speed to 95kHz in DCN401 - Allow higher DSC slice support for small timings on dcn401 - Don't offload flip if not only address update - Check UHBR13.5 cap when determining max link cap - Enable SYMCLK gating in DCCG - Expand to higher link rates - Add left edge pixel for YCbCr422/420 + ODM pipe split - Add resource interfaces for get ODM slice rect - Add COEF filter types for DCN401 - Refactor DCN401 DCCG into component directory - Fix 3dlut size for Fastloading on DCN401 - Fix write to non-existent reg on DCN401 - Remove USBC check for DCN32 - Remove unused code for some dc files - Disable AC/DC codepath when unnecessary - Create dcn401_clk_mgr struct Acked-by: Alex Hung Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d550b6f97039..a7ba80c84128 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,7 +55,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.284" +#define DC_VER "3.2.285" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 56116dc7a9fdd2ce2b0e01d16f772a766a0219e0 Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Fri, 10 May 2024 15:19:05 -0600 Subject: Revert "drm/amd/display: Enable SYMCLK gating in DCCG" This reverts commit c49e44ede5cdfe650c2f769d8bd58cbe289e87cd. This causes regression on DP link layer test. Reported-by: Mark Broadworth Acked-by: Rodrigo Siqueira Signed-off-by: Alex Hung Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 - .../gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c | 102 +++++++++------------ .../drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 45 +-------- .../drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h | 2 - .../gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c | 1 - .../drm/amd/display/dc/hwss/dcn351/dcn351_init.c | 1 - .../drm/amd/display/dc/hwss/hw_sequencer_private.h | 4 - drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h | 7 -- 8 files changed, 48 insertions(+), 115 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a7ba80c84128..fd948e4cec0d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -728,7 +728,6 @@ enum pg_hw_pipe_resources { PG_DPSTREAM, PG_HDMISTREAM, PG_PHYSYMCLK, - PG_SYMCLK, PG_HW_PIPE_RESOURCES_NUM_ELEMENT }; 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 d3b27920e294..1fc3aa2b507b 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 @@ -655,61 +655,9 @@ static void dccg35_disable_symclk32_se( } } -static void dccg35_set_symclk_root_clock_gating(struct dccg *dccg, uint32_t stream_enc_inst, - uint32_t link_enc_inst, bool enable) -{ - struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); - - switch (stream_enc_inst) { - case 0: - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); - break; - case 1: - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); - break; - case 2: - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); - break; - case 3: - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); - break; - case 4: - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); - break; - } - - switch (link_enc_inst) { - case 0: - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, enable ? 1 : 0); - break; - case 1: - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, enable ? 1 : 0); - break; - case 2: - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, enable ? 1 : 0); - break; - case 3: - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, enable ? 1 : 0); - break; - case 4: - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) - REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, enable ? 1 : 0); - break; - } -} - void dccg35_init(struct dccg *dccg) { - int otg_inst, phy_inst; + int otg_inst; /* 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. @@ -723,9 +671,10 @@ void dccg35_init(struct dccg *dccg) dccg31_set_symclk32_le_root_clock_gating(dccg, otg_inst, false); } - if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) - for (phy_inst = 0; phy_inst < 5; phy_inst++) - dccg35_set_symclk_root_clock_gating(dccg, phy_inst, phy_inst, false); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) +// for (otg_inst = 0; otg_inst < 4; otg_inst++) +// dccg35_disable_symclk_se(dccg, otg_inst, otg_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.dpstream) for (otg_inst = 0; otg_inst < 4; otg_inst++) { @@ -849,22 +798,32 @@ static void dccg35_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, case 0: REG_UPDATE(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, 1); break; case 1: REG_UPDATE(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, 1); break; case 2: REG_UPDATE(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, 1); break; case 3: REG_UPDATE(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, 1); break; case 4: REG_UPDATE(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, 1); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, 1); break; } @@ -873,26 +832,36 @@ static void dccg35_enable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst, REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, 1, SYMCLKA_FE_SRC_SEL, link_enc_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, 1); break; case 1: REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, 1, SYMCLKB_FE_SRC_SEL, link_enc_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, 1); break; case 2: REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, 1, SYMCLKC_FE_SRC_SEL, link_enc_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, 1); break; case 3: REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, 1, SYMCLKD_FE_SRC_SEL, link_enc_inst); + 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: REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_EN, 1, SYMCLKE_FE_SRC_SEL, link_enc_inst); + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, 1); break; } } @@ -953,26 +922,36 @@ static void dccg35_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_EN, 0, SYMCLKA_FE_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, 0); break; case 1: REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_EN, 0, SYMCLKB_FE_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, 0); break; case 2: REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_EN, 0, SYMCLKC_FE_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, 0); break; case 3: REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_EN, 0, SYMCLKD_FE_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, 0); break; case 4: REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_EN, 0, SYMCLKE_FE_SRC_SEL, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, 0); break; } @@ -985,22 +964,32 @@ static void dccg35_disable_symclk_se(struct dccg *dccg, uint32_t stream_enc_inst case 0: REG_UPDATE(SYMCLKA_CLOCK_ENABLE, SYMCLKA_CLOCK_ENABLE, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, 0); break; case 1: REG_UPDATE(SYMCLKB_CLOCK_ENABLE, SYMCLKB_CLOCK_ENABLE, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, 0); break; case 2: REG_UPDATE(SYMCLKC_CLOCK_ENABLE, SYMCLKC_CLOCK_ENABLE, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, 0); break; case 3: REG_UPDATE(SYMCLKD_CLOCK_ENABLE, SYMCLKD_CLOCK_ENABLE, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, 0); break; case 4: REG_UPDATE(SYMCLKE_CLOCK_ENABLE, SYMCLKE_CLOCK_ENABLE, 0); +// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_le) +// REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, 0); break; } } @@ -1033,7 +1022,6 @@ static const struct dccg_funcs dccg35_funcs = { .set_valid_pixel_rate = dccg35_set_valid_pixel_rate, .enable_symclk_se = dccg35_enable_symclk_se, .disable_symclk_se = dccg35_disable_symclk_se, - .set_symclk_root_clock_gating = dccg35_set_symclk_root_clock_gating, .set_dtbclk_p_src = dccg35_set_dtbclk_p_src, }; 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 6d9ec802f1bb..6d40e93b5497 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 @@ -519,17 +519,6 @@ void dcn35_physymclk_root_clock_control(struct dce_hwseq *hws, unsigned int phy_ } } -void dcn35_symclk_root_clock_control(struct dce_hwseq *hws, unsigned int enc_inst, bool clock_on) -{ - if (!hws->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) - return; - - if (hws->ctx->dc->res_pool->dccg->funcs->set_symclk_root_clock_gating) { - hws->ctx->dc->res_pool->dccg->funcs->set_symclk_root_clock_gating( - hws->ctx->dc->res_pool->dccg, enc_inst, enc_inst, clock_on); - } -} - void dcn35_dsc_pg_control( struct dce_hwseq *hws, unsigned int dsc_inst, @@ -1019,7 +1008,6 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, int i = 0, j = 0; int edp_num = 0; struct dc_link *edp_links[MAX_NUM_EDP] = { NULL }; - bool stream_enc_in_use[MAX_PIPES] = { false }; memset(update_state, 0, sizeof(struct pg_block_update)); @@ -1065,17 +1053,10 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context, 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->stream_res.stream_enc && - !pipe_ctx->stream_res.hpo_dp_stream_enc) - stream_enc_in_use[pipe_ctx->stream_res.stream_enc->stream_enc_inst] = true; } - for (i = 0; i < dc->res_pool->pipe_count; i++) - if (stream_enc_in_use[i]) - update_state->pg_pipe_res_update[PG_SYMCLK][i] = 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; } @@ -1139,10 +1120,6 @@ void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, 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; - - if (j == PG_SYMCLK && new_pipe->stream_res.stream_enc && - !new_pipe->stream_res.hpo_dp_stream_enc) - update_state->pg_pipe_res_update[j][new_pipe->stream_res.stream_enc->stream_enc_inst] = true; } } else if (cur_pipe->plane_state == new_pipe->plane_state || cur_pipe == new_pipe) { @@ -1177,12 +1154,6 @@ void dcn35_calc_blocks_to_ungate(struct dc *dc, struct dc_state *context, 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; - - if (j == PG_SYMCLK && - new_pipe->stream_res.stream_enc && - cur_pipe->stream_res.stream_enc != new_pipe->stream_res.stream_enc && - !new_pipe->stream_res.hpo_dp_stream_enc) - update_state->pg_pipe_res_update[j][new_pipe->stream_res.stream_enc->stream_enc_inst] = true; } } } @@ -1341,16 +1312,11 @@ void dcn35_root_clock_control(struct dc *dc, dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on); } - for (i = 0; i < dc->res_pool->dig_link_enc_count; i++) { + 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); - if (update_state->pg_pipe_res_update[PG_SYMCLK][i]) - if (dc->hwseq->funcs.symclk_root_clock_control) - dc->hwseq->funcs.symclk_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]) { @@ -1376,16 +1342,11 @@ void dcn35_root_clock_control(struct dc *dc, dc->hwseq->funcs.dpstream_root_clock_control(dc->hwseq, i, power_on); } - for (i = 0; i < dc->res_pool->dig_link_enc_count; i++) { + 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); - if (update_state->pg_pipe_res_update[PG_SYMCLK][i]) - if (dc->hwseq->funcs.symclk_root_clock_control) - dc->hwseq->funcs.symclk_root_clock_control(dc->hwseq, i, power_on); - } - } } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h index 503a8419bae7..bc05beba5f2c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.h @@ -41,8 +41,6 @@ void dcn35_dpstream_root_clock_control(struct dce_hwseq *hws, unsigned int dp_hp void dcn35_physymclk_root_clock_control(struct dce_hwseq *hws, unsigned int phy_inst, bool clock_on); -void dcn35_symclk_root_clock_control(struct dce_hwseq *hws, unsigned int enc_inst, bool clock_on); - void dcn35_enable_power_gating_plane(struct dce_hwseq *hws, bool enable); void dcn35_set_dmu_fgcg(struct dce_hwseq *hws, bool enable); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c index 0b6d7d76c85b..663bacd1fafd 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c @@ -150,7 +150,6 @@ static const struct hwseq_private_funcs dcn35_private_funcs = { .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, - .symclk_root_clock_control = dcn35_symclk_root_clock_control, .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, .update_odm = dcn35_update_odm, .set_hdr_multiplier = dcn10_set_hdr_multiplier, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c index e8643f305fd6..d8de1c6a84e8 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn351/dcn351_init.c @@ -149,7 +149,6 @@ static const struct hwseq_private_funcs dcn351_private_funcs = { .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, - .symclk_root_clock_control = dcn35_symclk_root_clock_control, .program_all_writeback_pipes_in_tree = dcn30_program_all_writeback_pipes_in_tree, .update_odm = dcn35_update_odm, .set_hdr_multiplier = dcn10_set_hdr_multiplier, 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 e2189795ca30..7ac3f2a09487 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 @@ -128,10 +128,6 @@ struct hwseq_private_funcs { struct dce_hwseq *hws, unsigned int phy_inst, bool clock_on); - void (*symclk_root_clock_control)( - struct dce_hwseq *hws, - unsigned int enc_inst, - bool clock_on); void (*dpp_pg_control)(struct dce_hwseq *hws, unsigned int dpp_inst, bool power_on); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h index 5b0924ea78af..867bc67aabfa 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h @@ -199,13 +199,6 @@ struct dccg_funcs { struct dccg *dccg, uint32_t stream_enc_inst, uint32_t link_enc_inst); - - void (*set_symclk_root_clock_gating)( - struct dccg *dccg, - uint32_t stream_enc_inst, - uint32_t link_enc_inst, - bool enable); - void (*set_dp_dto)( struct dccg *dccg, const struct dp_dto_params *params); -- cgit From 7a1dd866c5ac7d25bd1795e1cd507cabe29958ea Mon Sep 17 00:00:00 2001 From: Samson Tam Date: Wed, 24 Apr 2024 08:37:04 -0400 Subject: drm/amd/display: enable EASF support for DCN40 [Why] Enable adaptive scaler support for DCN401 [How] - Enable build flag for SPL - Set prefer_easf flag to true - Apply light linear scaling policy based on transfer function and pixel format. Choose between linear or non-linear scaling - Set matrix_mode based on pixel format - Disable ring estimator - Add missing EASF register defines, masks, and writes - Disable EASF if scale ratio or number of taps is unsupported and when bypassing the scaler - Add debug flags and registry keys for debugging SPL and EASF - Add support for Visual Confirm with EASF Reviewed-by: Rodrigo Siqueira Signed-off-by: Samson Tam Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 11 +- drivers/gpu/drm/amd/display/dc/dc.h | 3 + drivers/gpu/drm/amd/display/dc/dc_spl_translate.c | 15 +- .../gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h | 6 +- .../amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c | 207 ++++++++++++++++++++- .../display/dc/resource/dcn401/dcn401_resource.c | 1 + .../display/dc/resource/dcn401/dcn401_resource.h | 48 ++++- drivers/gpu/drm/amd/display/dc/spl/dc_spl.c | 95 ++++++++-- drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h | 30 ++- 9 files changed, 382 insertions(+), 34 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') 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 70c39eef99e5..ce1991e06049 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1500,8 +1500,8 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.scl_data.format = convert_pixel_format_to_dalsurface( pipe_ctx->plane_state->format); - if (pipe_ctx->stream->ctx->dc->config.use_spl) { #if defined(CONFIG_DRM_AMD_DC_FP) + if ((pipe_ctx->stream->ctx->dc->config.use_spl) && (!pipe_ctx->stream->ctx->dc->debug.disable_spl)) { struct spl_in *spl_in = &pipe_ctx->plane_res.spl_in; struct spl_out *spl_out = &pipe_ctx->plane_res.spl_out; @@ -1516,15 +1516,18 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) // Convert pipe_ctx to respective input params for SPL translate_SPL_in_params_from_pipe_ctx(pipe_ctx, spl_in); + /* Pass visual confirm debug information */ + calculate_adjust_recout_for_visual_confirm(pipe_ctx, + &spl_in->debug.visual_confirm_base_offset, + &spl_in->debug.visual_confirm_dpp_offset); // Set SPL output parameters to dscl_prog_data to be used for hw registers spl_out->dscl_prog_data = resource_get_dscl_prog_data(pipe_ctx); // Calculate scaler parameters from SPL res = spl_calculate_scaler_params(spl_in, spl_out); // Convert respective out params from SPL to scaler data translate_SPL_out_params_to_pipe_ctx(pipe_ctx, spl_out); -#endif } else { - +#endif /* depends on h_active */ calculate_recout(pipe_ctx); /* depends on pixel format */ @@ -1604,7 +1607,9 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.scl_data.viewport.height = MIN_VIEWPORT_SIZE; if (pipe_ctx->plane_res.scl_data.viewport.width < MIN_VIEWPORT_SIZE) pipe_ctx->plane_res.scl_data.viewport.width = MIN_VIEWPORT_SIZE; +#ifdef CONFIG_DRM_AMD_DC_FP } +#endif DC_LOG_SCALER("%s pipe %d:\nViewport: height:%d width:%d x:%d y:%d Recout: height:%d width:%d x:%d y:%d HACTIVE:%d VACTIVE:%d\n" "src_rect: height:%d width:%d x:%d y:%d dst_rect: height:%d width:%d x:%d y:%d clip_rect: height:%d width:%d x:%d y:%d\n", __func__, diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index fd948e4cec0d..5ae74558632b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1038,6 +1038,9 @@ struct dc_debug_options { union dmub_fams2_global_feature_config fams2_config; bool enable_legacy_clock_update; unsigned int force_cositing; + unsigned int disable_spl; + unsigned int force_easf; + unsigned int force_lls; }; 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 daf97688e901..6e37b166802b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c +++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c @@ -129,6 +129,11 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl populate_spltaps_from_taps(&spl_in->scaling_quality, &plane_state->scaling_quality); // Translate edge adaptive scaler preference spl_in->prefer_easf = pipe_ctx->stream->ctx->dc->config.prefer_easf; + spl_in->disable_easf = false; + if (pipe_ctx->stream->ctx->dc->debug.force_easf == 1) + spl_in->prefer_easf = false; + else if (pipe_ctx->stream->ctx->dc->debug.force_easf == 2) + spl_in->disable_easf = true; // Translate adaptive sharpening preference spl_in->adaptive_sharpness.enable = plane_state->adaptive_sharpness_en; if (plane_state->sharpnessX1000 == 0) { @@ -141,13 +146,19 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl spl_in->adaptive_sharpness.sharpness = SHARPNESS_HIGH; } // Translate linear light scaling preference - spl_in->lls_pref = plane_state->linear_light_scaling; - + if (pipe_ctx->stream->ctx->dc->debug.force_lls > 0) + spl_in->lls_pref = pipe_ctx->stream->ctx->dc->debug.force_lls; + else + spl_in->lls_pref = plane_state->linear_light_scaling; /* Translate chroma subsampling offset ( cositing ) */ if (pipe_ctx->stream->ctx->dc->debug.force_cositing) spl_in->basic_in.cositing = pipe_ctx->stream->ctx->dc->debug.force_cositing - 1; else spl_in->basic_in.cositing = plane_state->cositing; + /* Translate transfer function */ + spl_in->basic_in.tf_type = (enum spl_transfer_func_type) plane_state->in_transfer_func.type; + spl_in->basic_in.tf_predefined_type = (enum spl_transfer_func_predefined) plane_state->in_transfer_func.tf; + } /// @brief Translate SPL output parameters to pipe context 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 7ab657ad3a20..1aaae7a5bd41 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 @@ -373,7 +373,11 @@ 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_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_DCN401(type) \ DPP_REG_FIELD_LIST_DCN3(type); \ 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 d9a08cd160b3..4b1e52803c7a 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 @@ -294,7 +294,7 @@ static void dpp401_dscl_set_scl_filter( const uint16_t *filter_h_c = NULL; const uint16_t *filter_v_c = NULL; - if (dpp->base.ctx->dc->config.use_spl) { + if ((dpp->base.ctx->dc->config.use_spl) && (!dpp->base.ctx->dc->debug.disable_spl)) { filter_h = scl_data->dscl_prog_data.filter_h; filter_v = scl_data->dscl_prog_data.filter_v; filter_h_c = scl_data->dscl_prog_data.filter_h_c; @@ -523,7 +523,7 @@ static void dpp401_dscl_set_manual_ratio_init( { uint32_t init_frac = 0; uint32_t init_int = 0; - if (dpp->base.ctx->dc->config.use_spl) { + if ((dpp->base.ctx->dc->config.use_spl) && (!dpp->base.ctx->dc->debug.disable_spl)) { REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0, SCL_H_SCALE_RATIO, data->dscl_prog_data.ratios.h_scale_ratio); @@ -669,7 +669,7 @@ static void dpp401_dscl_program_easf(struct dpp *dpp_base, const struct scaler_d SCL_SC_MATRIX_MODE, scl_data->dscl_prog_data.easf_matrix_mode); REG_UPDATE(DSCL_SC_MODE, SCL_SC_LTONL_EN, scl_data->dscl_prog_data.easf_ltonl_en); - // DSCL_EASF_V_MODE + /* DSCL_EASF_V_MODE */ REG_UPDATE(DSCL_EASF_V_MODE, SCL_EASF_V_EN, scl_data->dscl_prog_data.easf_v_en); REG_UPDATE(DSCL_EASF_V_MODE, @@ -716,7 +716,87 @@ static void dpp401_dscl_program_easf(struct dpp *dpp_base, const struct scaler_d SCL_EASF_V_BF_MINA, scl_data->dscl_prog_data.easf_v_bf_mina); REG_UPDATE(DSCL_EASF_V_BF_FINAL_MAX_MIN, SCL_EASF_V_BF_MINB, scl_data->dscl_prog_data.easf_v_bf_minb); - // DSCL_EASF_H_MODE + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG0, + SCL_EASF_V_BF1_PWL_IN_SEG0, scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg0); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG0, + SCL_EASF_V_BF1_PWL_BASE_SEG0, scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg0); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG0, + SCL_EASF_V_BF1_PWL_SLOPE_SEG0, scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg0); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG1, + SCL_EASF_V_BF1_PWL_IN_SEG1, scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg1); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG1, + SCL_EASF_V_BF1_PWL_BASE_SEG1, scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg1); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG1, + SCL_EASF_V_BF1_PWL_SLOPE_SEG1, scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg1); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG2, + SCL_EASF_V_BF1_PWL_IN_SEG2, scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg2); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG2, + SCL_EASF_V_BF1_PWL_BASE_SEG2, scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg2); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG2, + SCL_EASF_V_BF1_PWL_SLOPE_SEG2, scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg2); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG3, + SCL_EASF_V_BF1_PWL_IN_SEG3, scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg3); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG3, + SCL_EASF_V_BF1_PWL_BASE_SEG3, scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg3); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG3, + SCL_EASF_V_BF1_PWL_SLOPE_SEG3, scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg3); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG4, + SCL_EASF_V_BF1_PWL_IN_SEG4, scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg4); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG4, + SCL_EASF_V_BF1_PWL_BASE_SEG4, scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg4); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG4, + SCL_EASF_V_BF1_PWL_SLOPE_SEG4, scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg4); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG5, + SCL_EASF_V_BF1_PWL_IN_SEG5, scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg5); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG5, + SCL_EASF_V_BF1_PWL_BASE_SEG5, scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg5); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG5, + SCL_EASF_V_BF1_PWL_SLOPE_SEG5, scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg5); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG6, + SCL_EASF_V_BF1_PWL_IN_SEG6, scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg6); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG6, + SCL_EASF_V_BF1_PWL_BASE_SEG6, scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg6); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG6, + SCL_EASF_V_BF1_PWL_SLOPE_SEG6, scl_data->dscl_prog_data.easf_v_bf1_pwl_slope_seg6); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG7, + SCL_EASF_V_BF1_PWL_IN_SEG7, scl_data->dscl_prog_data.easf_v_bf1_pwl_in_seg7); + REG_UPDATE(DSCL_EASF_V_BF1_PWL_SEG7, + SCL_EASF_V_BF1_PWL_BASE_SEG7, scl_data->dscl_prog_data.easf_v_bf1_pwl_base_seg7); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG0, + SCL_EASF_V_BF3_PWL_IN_SEG0, scl_data->dscl_prog_data.easf_v_bf3_pwl_in_set0); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG0, + SCL_EASF_V_BF3_PWL_BASE_SEG0, scl_data->dscl_prog_data.easf_v_bf3_pwl_base_set0); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG0, + SCL_EASF_V_BF3_PWL_SLOPE_SEG0, scl_data->dscl_prog_data.easf_v_bf3_pwl_slope_set0); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG1, + SCL_EASF_V_BF3_PWL_IN_SEG1, scl_data->dscl_prog_data.easf_v_bf3_pwl_in_set1); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG1, + SCL_EASF_V_BF3_PWL_BASE_SEG1, scl_data->dscl_prog_data.easf_v_bf3_pwl_base_set1); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG1, + SCL_EASF_V_BF3_PWL_SLOPE_SEG1, scl_data->dscl_prog_data.easf_v_bf3_pwl_slope_set1); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG2, + SCL_EASF_V_BF3_PWL_IN_SEG2, scl_data->dscl_prog_data.easf_v_bf3_pwl_in_set2); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG2, + SCL_EASF_V_BF3_PWL_BASE_SEG2, scl_data->dscl_prog_data.easf_v_bf3_pwl_base_set2); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG2, + SCL_EASF_V_BF3_PWL_SLOPE_SEG2, scl_data->dscl_prog_data.easf_v_bf3_pwl_slope_set2); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG3, + SCL_EASF_V_BF3_PWL_IN_SEG3, scl_data->dscl_prog_data.easf_v_bf3_pwl_in_set3); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG3, + SCL_EASF_V_BF3_PWL_BASE_SEG3, scl_data->dscl_prog_data.easf_v_bf3_pwl_base_set3); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG3, + SCL_EASF_V_BF3_PWL_SLOPE_SEG3, scl_data->dscl_prog_data.easf_v_bf3_pwl_slope_set3); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG4, + SCL_EASF_V_BF3_PWL_IN_SEG4, scl_data->dscl_prog_data.easf_v_bf3_pwl_in_set4); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG4, + SCL_EASF_V_BF3_PWL_BASE_SEG4, scl_data->dscl_prog_data.easf_v_bf3_pwl_base_set4); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG4, + SCL_EASF_V_BF3_PWL_SLOPE_SEG4, scl_data->dscl_prog_data.easf_v_bf3_pwl_slope_set4); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG5, + SCL_EASF_V_BF3_PWL_IN_SEG5, scl_data->dscl_prog_data.easf_v_bf3_pwl_in_set5); + REG_UPDATE(DSCL_EASF_V_BF3_PWL_SEG5, + SCL_EASF_V_BF3_PWL_BASE_SEG5, scl_data->dscl_prog_data.easf_v_bf3_pwl_base_set5); + /* DSCL_EASF_H_MODE */ REG_UPDATE(DSCL_EASF_H_MODE, SCL_EASF_H_EN, scl_data->dscl_prog_data.easf_h_en); REG_UPDATE(DSCL_EASF_H_MODE, @@ -751,6 +831,117 @@ static void dpp401_dscl_program_easf(struct dpp *dpp_base, const struct scaler_d SCL_EASF_H_BF_MINA, scl_data->dscl_prog_data.easf_h_bf_mina); REG_UPDATE(DSCL_EASF_H_BF_FINAL_MAX_MIN, SCL_EASF_H_BF_MINB, scl_data->dscl_prog_data.easf_h_bf_minb); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG0, + SCL_EASF_H_BF1_PWL_IN_SEG0, scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg0); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG0, + SCL_EASF_H_BF1_PWL_BASE_SEG0, scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg0); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG0, + SCL_EASF_H_BF1_PWL_SLOPE_SEG0, scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg0); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG1, + SCL_EASF_H_BF1_PWL_IN_SEG1, scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg1); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG1, + SCL_EASF_H_BF1_PWL_BASE_SEG1, scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg1); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG1, + SCL_EASF_H_BF1_PWL_SLOPE_SEG1, scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg1); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG2, + SCL_EASF_H_BF1_PWL_IN_SEG2, scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg2); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG2, + SCL_EASF_H_BF1_PWL_BASE_SEG2, scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg2); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG2, + SCL_EASF_H_BF1_PWL_SLOPE_SEG2, scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg2); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG3, + SCL_EASF_H_BF1_PWL_IN_SEG3, scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg3); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG3, + SCL_EASF_H_BF1_PWL_BASE_SEG3, scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg3); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG3, + SCL_EASF_H_BF1_PWL_SLOPE_SEG3, scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg3); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG4, + SCL_EASF_H_BF1_PWL_IN_SEG4, scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg4); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG4, + SCL_EASF_H_BF1_PWL_BASE_SEG4, scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg4); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG4, + SCL_EASF_H_BF1_PWL_SLOPE_SEG4, scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg4); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG5, + SCL_EASF_H_BF1_PWL_IN_SEG5, scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg5); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG5, + SCL_EASF_H_BF1_PWL_BASE_SEG5, scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg5); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG5, + SCL_EASF_H_BF1_PWL_SLOPE_SEG5, scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg5); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG6, + SCL_EASF_H_BF1_PWL_IN_SEG6, scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg6); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG6, + SCL_EASF_H_BF1_PWL_BASE_SEG6, scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg6); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG6, + SCL_EASF_H_BF1_PWL_SLOPE_SEG6, scl_data->dscl_prog_data.easf_h_bf1_pwl_slope_seg6); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG7, + SCL_EASF_H_BF1_PWL_IN_SEG7, scl_data->dscl_prog_data.easf_h_bf1_pwl_in_seg7); + REG_UPDATE(DSCL_EASF_H_BF1_PWL_SEG7, + SCL_EASF_H_BF1_PWL_BASE_SEG7, scl_data->dscl_prog_data.easf_h_bf1_pwl_base_seg7); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG0, + SCL_EASF_H_BF3_PWL_IN_SEG0, scl_data->dscl_prog_data.easf_h_bf3_pwl_in_set0); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG0, + SCL_EASF_H_BF3_PWL_BASE_SEG0, scl_data->dscl_prog_data.easf_h_bf3_pwl_base_set0); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG0, + SCL_EASF_H_BF3_PWL_SLOPE_SEG0, scl_data->dscl_prog_data.easf_h_bf3_pwl_slope_set0); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG1, + SCL_EASF_H_BF3_PWL_IN_SEG1, scl_data->dscl_prog_data.easf_h_bf3_pwl_in_set1); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG1, + SCL_EASF_H_BF3_PWL_BASE_SEG1, scl_data->dscl_prog_data.easf_h_bf3_pwl_base_set1); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG1, + SCL_EASF_H_BF3_PWL_SLOPE_SEG1, scl_data->dscl_prog_data.easf_h_bf3_pwl_slope_set1); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG2, + SCL_EASF_H_BF3_PWL_IN_SEG2, scl_data->dscl_prog_data.easf_h_bf3_pwl_in_set2); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG2, + SCL_EASF_H_BF3_PWL_BASE_SEG2, scl_data->dscl_prog_data.easf_h_bf3_pwl_base_set2); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG2, + SCL_EASF_H_BF3_PWL_SLOPE_SEG2, scl_data->dscl_prog_data.easf_h_bf3_pwl_slope_set2); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG3, + SCL_EASF_H_BF3_PWL_IN_SEG3, scl_data->dscl_prog_data.easf_h_bf3_pwl_in_set3); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG3, + SCL_EASF_H_BF3_PWL_BASE_SEG3, scl_data->dscl_prog_data.easf_h_bf3_pwl_base_set3); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG3, + SCL_EASF_H_BF3_PWL_SLOPE_SEG3, scl_data->dscl_prog_data.easf_h_bf3_pwl_slope_set3); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG4, + SCL_EASF_H_BF3_PWL_IN_SEG4, scl_data->dscl_prog_data.easf_h_bf3_pwl_in_set4); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG4, + SCL_EASF_H_BF3_PWL_BASE_SEG4, scl_data->dscl_prog_data.easf_h_bf3_pwl_base_set4); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG4, + SCL_EASF_H_BF3_PWL_SLOPE_SEG4, scl_data->dscl_prog_data.easf_h_bf3_pwl_slope_set4); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG5, + SCL_EASF_H_BF3_PWL_IN_SEG5, scl_data->dscl_prog_data.easf_h_bf3_pwl_in_set5); + REG_UPDATE(DSCL_EASF_H_BF3_PWL_SEG5, + SCL_EASF_H_BF3_PWL_BASE_SEG5, scl_data->dscl_prog_data.easf_h_bf3_pwl_base_set5); + /* DSCL_EASF_SC_MATRIX_C0C1, DSCL_EASF_SC_MATRIX_C2C3 */ + REG_UPDATE(DSCL_SC_MATRIX_C0C1, + SCL_SC_MATRIX_C0, scl_data->dscl_prog_data.easf_matrix_c0); + REG_UPDATE(DSCL_SC_MATRIX_C0C1, + SCL_SC_MATRIX_C1, scl_data->dscl_prog_data.easf_matrix_c1); + REG_UPDATE(DSCL_SC_MATRIX_C2C3, + SCL_SC_MATRIX_C2, scl_data->dscl_prog_data.easf_matrix_c2); + REG_UPDATE(DSCL_SC_MATRIX_C2C3, + SCL_SC_MATRIX_C3, scl_data->dscl_prog_data.easf_matrix_c3); + PERF_TRACE(); +} +/** + * dpp401_dscl_disable_easf - Disable EASF when no scaling (1:1) + * + * @dpp_base: High level DPP struct + * @scl_data: scalaer_data info + * + * When we have 1:1 scaling, we need to disable EASF + * + */ +static void dpp401_dscl_disable_easf(struct dpp *dpp_base, const struct scaler_data *scl_data) +{ + struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base); + + PERF_TRACE(); + /* DSCL_EASF_V_MODE */ + REG_UPDATE(DSCL_EASF_V_MODE, + SCL_EASF_V_EN, scl_data->dscl_prog_data.easf_v_en); + /* DSCL_EASF_H_MODE */ + REG_UPDATE(DSCL_EASF_H_MODE, + SCL_EASF_H_EN, scl_data->dscl_prog_data.easf_h_en); PERF_TRACE(); } static void dpp401_dscl_set_isharp_filter( @@ -852,7 +1043,7 @@ void dpp401_dscl_set_scaler_manual_scale(struct dpp *dpp_base, dpp->scl_data = *scl_data; - if (dpp->base.ctx->dc->config.use_spl) { + if ((dpp->base.ctx->dc->config.use_spl) && (!dpp->base.ctx->dc->debug.disable_spl)) { dscl_mode = (enum dscl_mode_sel) scl_data->dscl_prog_data.dscl_mode; rect = (struct rect *)&scl_data->dscl_prog_data.recout; mpc_width = scl_data->dscl_prog_data.mpc_size.width; @@ -900,8 +1091,12 @@ void dpp401_dscl_set_scaler_manual_scale(struct dpp *dpp_base, lb_config = dpp401_dscl_find_lb_memory_config(dpp, scl_data); dpp401_dscl_set_lb(dpp, &scl_data->lb_params, lb_config); - if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) + if (dscl_mode == DSCL_MODE_SCALING_444_BYPASS) { + if (dpp->base.ctx->dc->config.prefer_easf) + dpp401_dscl_disable_easf(dpp_base, scl_data); + dpp401_dscl_program_isharp(dpp_base, scl_data); return; + } /* Black offsets */ if (REG(SCL_BLACK_OFFSET)) { 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 a55421363772..fc43e7b5ec90 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 @@ -1845,6 +1845,7 @@ static bool dcn401_resource_construct( dc->caps.color.mpc.ogam_rom_caps.hlg = 0; dc->caps.color.mpc.ocsc = 1; dc->config.use_spl = true; + dc->config.prefer_easf = true; dc->config.dc_mode_clk_limit_support = true; dc->config.enable_windowed_mpo_odm = true; /* read VBIOS LTTPR caps */ 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 5d5e01903ca1..a638c410e32a 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 @@ -342,7 +342,53 @@ bool dcn401_validate_bandwidth(struct dc *dc, 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_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(SCL_VERT_FILTER_INIT_BOT, DSCL, id), \ + SRI_ARR(SCL_VERT_FILTER_INIT_BOT_C, DSCL, id) /* OPP */ #define OPP_REG_LIST_DCN401_RI(id) \ diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c index 542cd6cdef46..82fbd2b59c70 100644 --- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c +++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c @@ -324,14 +324,18 @@ static void spl_calculate_recout(struct spl_in *spl_in, struct spl_out *spl_out) overlapping_area = intersect_rec(&mpc_slice_of_plane_clip, &odm_slice); if (overlapping_area.height > 0 && - overlapping_area.width > 0) + overlapping_area.width > 0) { /* shift the overlapping area so it is with respect to current * ODM slice's position */ spl_out->scl_data.recout = shift_rec( &overlapping_area, -odm_slice.x, -odm_slice.y); - else + spl_out->scl_data.recout.height -= + spl_in->debug.visual_confirm_base_offset; + spl_out->scl_data.recout.height -= + spl_in->debug.visual_confirm_dpp_offset; + } else /* if there is no overlap, zero recout */ memset(&spl_out->scl_data.recout, 0, sizeof(struct spl_rect)); @@ -493,13 +497,11 @@ static void spl_calculate_init_and_vp(bool flip_scan_dir, static bool spl_is_yuv420(enum spl_pixel_format format) { - switch (format) { - case SPL_PIXEL_FORMAT_420BPP8: - case SPL_PIXEL_FORMAT_420BPP10: + if ((format >= SPL_PIXEL_FORMAT_VIDEO_BEGIN) && + (format <= SPL_PIXEL_FORMAT_VIDEO_END)) return true; - default: - return false; - } + + return false; } /*Calculate inits and viewport */ @@ -969,12 +971,17 @@ static bool enable_easf(int scale_ratio, int taps, } /* Set EASF data */ static void spl_set_easf_data(struct dscl_prog_data *dscl_prog_data, - bool enable_easf_v, bool enable_easf_h, enum linear_light_scaling lls_pref) + bool enable_easf_v, bool enable_easf_h, enum linear_light_scaling lls_pref, + enum spl_pixel_format format) { - dscl_prog_data->easf_matrix_mode = 0; + if (spl_is_yuv420(format)) /* TODO: 0 = RGB, 1 = YUV */ + dscl_prog_data->easf_matrix_mode = 1; + else + dscl_prog_data->easf_matrix_mode = 0; + if (enable_easf_v) { dscl_prog_data->easf_v_en = true; - dscl_prog_data->easf_v_ring = 1; + dscl_prog_data->easf_v_ring = 0; dscl_prog_data->easf_v_sharp_factor = 1; dscl_prog_data->easf_v_bf1_en = 1; // 1-bit, BF1 calculation enable, 0=disable, 1=enable dscl_prog_data->easf_v_bf2_mode = 0xF; // 4-bit, BF2 calculation mode @@ -1081,10 +1088,12 @@ static void spl_set_easf_data(struct dscl_prog_data *dscl_prog_data, 0x0780; // FP0.6.6, BF3 Input value PWL Segment 5 (0.5) dscl_prog_data->easf_v_bf3_pwl_base_set5 = -63; // S0.6, BF3 Base PWL Segment 5 } - } + } else + dscl_prog_data->easf_v_en = false; + if (enable_easf_h) { dscl_prog_data->easf_h_en = true; - dscl_prog_data->easf_h_ring = 1; + dscl_prog_data->easf_h_ring = 0; dscl_prog_data->easf_h_sharp_factor = 1; dscl_prog_data->easf_h_bf1_en = 1; // 1-bit, BF1 calculation enable, 0=disable, 1=enable @@ -1177,7 +1186,9 @@ static void spl_set_easf_data(struct dscl_prog_data *dscl_prog_data, 0x0780; // FP0.6.6, BF3 Input value PWL Segment 5 (0.5) dscl_prog_data->easf_h_bf3_pwl_base_set5 = -63; // S0.6, BF3 Base PWL Segment 5 } // if (lls_pref == LLS_PREF_YES) - } + } else + dscl_prog_data->easf_h_en = false; + if (lls_pref == LLS_PREF_YES) { dscl_prog_data->easf_ltonl_en = 1; // Linear input dscl_prog_data->easf_matrix_c0 = @@ -1304,12 +1315,40 @@ static bool spl_get_isharp_en(struct adaptive_sharpness adp_sharpness, } return enable_isharp; } + +static bool spl_choose_lls_policy(enum spl_pixel_format format, + enum spl_transfer_func_type tf_type, + enum spl_transfer_func_predefined tf_predefined_type, + enum linear_light_scaling *lls_pref) +{ + if (spl_is_yuv420(format)) { + *lls_pref = LLS_PREF_NO; + if ((tf_type == SPL_TF_TYPE_PREDEFINED) || (tf_type == SPL_TF_TYPE_DISTRIBUTED_POINTS)) + return true; + } else { /* RGB or YUV444 */ + if (tf_type == SPL_TF_TYPE_PREDEFINED) { + if ((tf_predefined_type == SPL_TRANSFER_FUNCTION_HLG) || + (tf_predefined_type == SPL_TRANSFER_FUNCTION_HLG12)) + *lls_pref = LLS_PREF_NO; + else + *lls_pref = LLS_PREF_YES; + return true; + } else if (tf_type == SPL_TF_TYPE_BYPASS) { + *lls_pref = LLS_PREF_YES; + return true; + } + } + *lls_pref = LLS_PREF_NO; + return false; +} + /* Caclulate scaler parameters */ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out) { bool res = false; bool enable_easf_v = false; bool enable_easf_h = false; + bool lls_enable_easf = true; // All SPL calls /* recout calculation */ /* depends on h_active */ @@ -1335,17 +1374,33 @@ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out) if (!res) return res; + + /* + * If lls_pref is LLS_PREF_DONT_CARE, then use pixel format and transfer + * function to determine whether to use LINEAR or NONLINEAR scaling + */ + if (spl_in->lls_pref == LLS_PREF_DONT_CARE) + lls_enable_easf = spl_choose_lls_policy(spl_in->basic_in.format, + spl_in->basic_in.tf_type, spl_in->basic_in.tf_predefined_type, + &spl_in->lls_pref); + // Save all calculated parameters in dscl_prog_data structure to program hw registers spl_set_dscl_prog_data(spl_in, spl_out); - // Enable EASF on vertical? + int vratio = dc_fixpt_ceil(spl_out->scl_data.ratios.vert); int hratio = dc_fixpt_ceil(spl_out->scl_data.ratios.horz); - enable_easf_v = enable_easf(vratio, spl_out->scl_data.taps.v_taps, spl_in->lls_pref, spl_in->prefer_easf); - // Enable EASF on horizontal? - enable_easf_h = enable_easf(hratio, spl_out->scl_data.taps.h_taps, spl_in->lls_pref, spl_in->prefer_easf); + if (!lls_enable_easf || spl_in->disable_easf) { + enable_easf_v = false; + enable_easf_h = false; + } else { + /* Enable EASF on vertical? */ + enable_easf_v = enable_easf(vratio, spl_out->scl_data.taps.v_taps, spl_in->lls_pref, spl_in->prefer_easf); + /* Enable EASF on horizontal? */ + enable_easf_h = enable_easf(hratio, spl_out->scl_data.taps.h_taps, spl_in->lls_pref, spl_in->prefer_easf); + } // Set EASF - spl_set_easf_data(spl_out->dscl_prog_data, enable_easf_v, enable_easf_h, spl_in->lls_pref); - // Set iSHARP + spl_set_easf_data(spl_out->dscl_prog_data, enable_easf_v, enable_easf_h, spl_in->lls_pref, + spl_in->basic_in.format); // Set iSHARP bool enable_isharp = spl_get_isharp_en(spl_in->adaptive_sharpness, vratio, hratio, spl_out->scl_data.taps); if (enable_isharp) diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h index c5ef15f16c68..0c9edee0582e 100644 --- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h +++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h @@ -132,6 +132,26 @@ struct spl_scaler_data { struct spl_inits inits; }; +enum spl_transfer_func_type { + SPL_TF_TYPE_PREDEFINED, + SPL_TF_TYPE_DISTRIBUTED_POINTS, + SPL_TF_TYPE_BYPASS, + SPL_TF_TYPE_HWPWL +}; + +enum spl_transfer_func_predefined { + SPL_TRANSFER_FUNCTION_SRGB, + SPL_TRANSFER_FUNCTION_BT709, + SPL_TRANSFER_FUNCTION_PQ, + SPL_TRANSFER_FUNCTION_LINEAR, + SPL_TRANSFER_FUNCTION_UNITY, + SPL_TRANSFER_FUNCTION_HLG, + SPL_TRANSFER_FUNCTION_HLG12, + SPL_TRANSFER_FUNCTION_GAMMA22, + SPL_TRANSFER_FUNCTION_GAMMA24, + SPL_TRANSFER_FUNCTION_GAMMA26 +}; + /*==============================================================*/ /* Below structs are defined to hold hw register data */ @@ -400,7 +420,8 @@ struct basic_in { int mpc_combine_h; // MPC Horizontal Combine Factor (split_count) int mpc_combine_v; // MPC Vertical Combine Factor (split_idx) // Inputs for adaptive scaler - TODO - // struct dc_transfer_func transfer_func; // Transfer function + enum spl_transfer_func_type tf_type; /* Transfer function type */ + enum spl_transfer_func_predefined tf_predefined_type; /* Transfer function predefined type */ // enum dc_transfer_func_predefined tf; enum spl_color_space color_space; // Color Space unsigned int max_luminance; // Max Luminance TODO: Is determined in dc_hw_sequencer.c is_sdr @@ -441,6 +462,11 @@ struct spl_funcs { int *num_part_c); }; +struct spl_debug { + int visual_confirm_base_offset; + int visual_confirm_dpp_offset; +}; + struct spl_in { struct basic_out basic_out; struct basic_in basic_in; @@ -452,6 +478,8 @@ struct spl_in { struct adaptive_sharpness adaptive_sharpness; // Adaptive Sharpness enum linear_light_scaling lls_pref; // Linear Light Scaling bool prefer_easf; + bool disable_easf; + struct spl_debug debug; }; // end of SPL inputs -- cgit From 6e3726419bfc8ab52e7a54b376b4c73282203807 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 12 May 2024 20:21:53 -0400 Subject: drm/amd/display: 3.2.286 This version pairs with DMUB FW Release 0.0.218.0 for dcn314/315/316, dcn35/351, dcn401 and brings along the following: - Fix powerpc compilation - Fix TBT+TypeC Daisy-chain lightup - Fix ODM combine setup - Fix OTC underflow on dcn35 - Fix DVI config for dcn401 - Add ips status info to debugfs - Add 3DLUT DMA load trigger - Modify clock programming to support DPM - Disable dcn401 idle optimizations Acked-by: Roman Li Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5ae74558632b..a711e3fd6f1b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,7 +55,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.285" +#define DC_VER "3.2.286" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit From 2998bccfa4197ff49bf70cbe14563d1417fe3ccf Mon Sep 17 00:00:00 2001 From: Samson Tam Date: Fri, 26 Apr 2024 12:17:26 -0400 Subject: drm/amd/display: Enable ISHARP support for DCN401 [Why] Enable sharpener support for DCN401 [How] - Removed memcmp check that was preventing ISHARP from being enabled. - Add missing ISHARP register defines, masks, and writes. - Add programming of Blur and Scale coefficients. - Program FMT_MODE and NLDELTA registers based on LLS_PREF and pixel - format - Only enable ISHARP for YUV420 - Add disabling of ISHARP - Add debug flags and registry keys for debugging ISHARP. - Set default to medium level Acked-by: Rodrigo Siqueira Signed-off-by: Samson Tam Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dc_spl_translate.c | 29 ++-- .../amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c | 149 ++++++++++++++++----- .../display/dc/resource/dcn401/dcn401_resource.h | 13 ++ drivers/gpu/drm/amd/display/dc/spl/dc_spl.c | 81 ++++++++--- .../drm/amd/display/dc/spl/dc_spl_isharp_filters.c | 8 +- .../drm/amd/display/dc/spl/dc_spl_isharp_filters.h | 4 +- drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h | 3 + 8 files changed, 223 insertions(+), 65 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index a711e3fd6f1b..1055970d3888 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1040,6 +1040,7 @@ struct dc_debug_options { unsigned int force_cositing; unsigned int disable_spl; unsigned int force_easf; + unsigned int force_sharpness; unsigned int force_lls; }; 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 6e37b166802b..bc760448a378 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c +++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c @@ -134,16 +134,25 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl spl_in->prefer_easf = false; else if (pipe_ctx->stream->ctx->dc->debug.force_easf == 2) spl_in->disable_easf = true; - // Translate adaptive sharpening preference - spl_in->adaptive_sharpness.enable = plane_state->adaptive_sharpness_en; - if (plane_state->sharpnessX1000 == 0) { - spl_in->adaptive_sharpness.enable = false; - } else if (plane_state->sharpnessX1000 < 999) { - spl_in->adaptive_sharpness.sharpness = SHARPNESS_LOW; - } else if (plane_state->sharpnessX1000 < 1999) { - spl_in->adaptive_sharpness.sharpness = SHARPNESS_MID; - } else { // Any other value is high sharpness - spl_in->adaptive_sharpness.sharpness = SHARPNESS_HIGH; + /* Translate adaptive sharpening preference */ + if (pipe_ctx->stream->ctx->dc->debug.force_sharpness > 0) { + spl_in->adaptive_sharpness.enable = (pipe_ctx->stream->ctx->dc->debug.force_sharpness > 1) ? true : false; + if (pipe_ctx->stream->ctx->dc->debug.force_sharpness == 2) + spl_in->adaptive_sharpness.sharpness = SHARPNESS_LOW; + else if (pipe_ctx->stream->ctx->dc->debug.force_sharpness == 3) + spl_in->adaptive_sharpness.sharpness = SHARPNESS_MID; + else if (pipe_ctx->stream->ctx->dc->debug.force_sharpness >= 4) + spl_in->adaptive_sharpness.sharpness = SHARPNESS_HIGH; + } else { + spl_in->adaptive_sharpness.enable = plane_state->adaptive_sharpness_en; + if (plane_state->sharpnessX1000 == 0) + spl_in->adaptive_sharpness.enable = false; + else if (plane_state->sharpnessX1000 < 999) + spl_in->adaptive_sharpness.sharpness = SHARPNESS_LOW; + else if (plane_state->sharpnessX1000 < 1999) + spl_in->adaptive_sharpness.sharpness = SHARPNESS_MID; + else // Any other value is high sharpness + spl_in->adaptive_sharpness.sharpness = SHARPNESS_HIGH; } // Translate linear light scaling preference if (pipe_ctx->stream->ctx->dc->debug.force_lls > 0) 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 4b1e52803c7a..6cb3fa4b585c 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 @@ -949,6 +949,9 @@ static void dpp401_dscl_set_isharp_filter( { int level; uint32_t filter_data; + if (filter == NULL) + return; + REG_UPDATE(ISHARP_DELTA_CTRL, ISHARP_DELTA_LUT_HOST_SELECT, 0); for (level = 0; level < NUM_LEVELS; level++) { @@ -972,41 +975,121 @@ static void dpp401_dscl_program_isharp(struct dpp *dpp_base, const struct scaler_data *scl_data) { struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base); - const struct dscl_prog_data *data; - - if (memcmp(&dpp->scl_data, scl_data, sizeof(*scl_data)) == 0) - return; PERF_TRACE(); - dpp->scl_data = *scl_data; - data = &scl_data->dscl_prog_data; - - REG_SET(ISHARP_MODE, 0, ISHARP_EN, data->isharp_en); - - REG_SET(ISHARP_MODE, 0, ISHARP_NOISEDET_EN, data->isharp_noise_det.enable); - REG_SET(ISHARP_MODE, 0, ISHARP_NOISEDET_MODE, data->isharp_noise_det.mode); - REG_SET(ISHARP_NOISEDET_THRESHOLD, 0, ISHARP_NOISEDET_UTHRE, data->isharp_noise_det.uthreshold); - REG_SET(ISHARP_NOISEDET_THRESHOLD, 0, ISHARP_NOISEDET_DTHRE, data->isharp_noise_det.dthreshold); - REG_SET(ISHARP_MODE, 0, ISHARP_NOISEDET_MODE, data->isharp_noise_det.mode); - REG_SET(ISHARP_NOISEDET_THRESHOLD, 0, ISHARP_NOISEDET_UTHRE, data->isharp_noise_det.uthreshold); - REG_SET(ISHARP_NOISEDET_THRESHOLD, 0, ISHARP_NOISEDET_DTHRE, data->isharp_noise_det.dthreshold); - REG_SET(ISHARP_NOISE_GAIN_PWL, 0, ISHARP_NOISEDET_PWL_START_IN, data->isharp_noise_det.pwl_start_in); - REG_SET(ISHARP_NOISE_GAIN_PWL, 0, ISHARP_NOISEDET_PWL_END_IN, data->isharp_noise_det.pwl_end_in); - REG_SET(ISHARP_NOISE_GAIN_PWL, 0, ISHARP_NOISEDET_PWL_SLOPE, data->isharp_noise_det.pwl_slope); - - REG_SET(ISHARP_MODE, 0, ISHARP_LBA_MODE, data->isharp_lba.mode); - // TODO: ISHARP_LBA: IN_SEG, BASE_SEG, SLOPE_SEG - REG_SET(ISHARP_MODE, 0, ISHARP_FMT_MODE, data->isharp_fmt.mode); - REG_SET(ISHARP_MODE, 0, ISHARP_FMT_NORM, data->isharp_fmt.norm); - - dpp401_dscl_set_isharp_filter(dpp, data->isharp_delta); - - REG_SET(ISHARP_NLDELTA_SOFT_CLIP, 0, ISHARP_NLDELTA_SCLIP_EN_P, data->isharp_nldelta_sclip.enable_p); - REG_SET(ISHARP_NLDELTA_SOFT_CLIP, 0, ISHARP_NLDELTA_SCLIP_PIVOT_P, data->isharp_nldelta_sclip.pivot_p); - REG_SET(ISHARP_NLDELTA_SOFT_CLIP, 0, ISHARP_NLDELTA_SCLIP_SLOPE_P, data->isharp_nldelta_sclip.slope_p); - REG_SET(ISHARP_NLDELTA_SOFT_CLIP, 0, ISHARP_NLDELTA_SCLIP_EN_N, data->isharp_nldelta_sclip.enable_n); - REG_SET(ISHARP_NLDELTA_SOFT_CLIP, 0, ISHARP_NLDELTA_SCLIP_PIVOT_N, data->isharp_nldelta_sclip.pivot_n); - REG_SET(ISHARP_NLDELTA_SOFT_CLIP, 0, ISHARP_NLDELTA_SCLIP_SLOPE_N, data->isharp_nldelta_sclip.slope_n); + /* ISHARP_EN */ + REG_UPDATE(ISHARP_MODE, + ISHARP_EN, scl_data->dscl_prog_data.isharp_en); + /* ISHARP_NOISEDET_EN */ + REG_UPDATE(ISHARP_MODE, + ISHARP_NOISEDET_EN, scl_data->dscl_prog_data.isharp_noise_det.enable); + /* ISHARP_NOISEDET_MODE */ + REG_UPDATE(ISHARP_MODE, + ISHARP_NOISEDET_MODE, scl_data->dscl_prog_data.isharp_noise_det.mode); + /* ISHARP_NOISEDET_UTHRE */ + REG_UPDATE(ISHARP_NOISEDET_THRESHOLD, + ISHARP_NOISEDET_UTHRE, scl_data->dscl_prog_data.isharp_noise_det.uthreshold); + /* ISHARP_NOISEDET_DTHRE */ + REG_UPDATE(ISHARP_NOISEDET_THRESHOLD, + ISHARP_NOISEDET_DTHRE, scl_data->dscl_prog_data.isharp_noise_det.dthreshold); + REG_UPDATE(ISHARP_MODE, + ISHARP_NOISEDET_MODE, scl_data->dscl_prog_data.isharp_noise_det.mode); + /* ISHARP_NOISEDET_UTHRE */ + REG_UPDATE(ISHARP_NOISEDET_THRESHOLD, + ISHARP_NOISEDET_UTHRE, scl_data->dscl_prog_data.isharp_noise_det.uthreshold); + /* ISHARP_NOISEDET_DTHRE */ + REG_UPDATE(ISHARP_NOISEDET_THRESHOLD, + ISHARP_NOISEDET_DTHRE, scl_data->dscl_prog_data.isharp_noise_det.dthreshold); + /* ISHARP_NOISEDET_PWL_START_IN */ + REG_UPDATE(ISHARP_NOISE_GAIN_PWL, + ISHARP_NOISEDET_PWL_START_IN, scl_data->dscl_prog_data.isharp_noise_det.pwl_start_in); + /* ISHARP_NOISEDET_PWL_END_IN */ + REG_UPDATE(ISHARP_NOISE_GAIN_PWL, + ISHARP_NOISEDET_PWL_END_IN, scl_data->dscl_prog_data.isharp_noise_det.pwl_end_in); + /* ISHARP_NOISEDET_PWL_SLOPE */ + REG_UPDATE(ISHARP_NOISE_GAIN_PWL, + ISHARP_NOISEDET_PWL_SLOPE, scl_data->dscl_prog_data.isharp_noise_det.pwl_slope); + /* ISHARP_LBA_MODE */ + REG_UPDATE(ISHARP_MODE, + ISHARP_LBA_MODE, scl_data->dscl_prog_data.isharp_lba.mode); + /* ISHARP_LBA: IN_SEG, BASE_SEG, SLOPE_SEG */ + REG_UPDATE(ISHARP_LBA_PWL_SEG0, + ISHARP_LBA_PWL_IN_SEG0, scl_data->dscl_prog_data.isharp_lba.in_seg[0]); + REG_UPDATE(ISHARP_LBA_PWL_SEG0, + ISHARP_LBA_PWL_BASE_SEG0, scl_data->dscl_prog_data.isharp_lba.base_seg[0]); + REG_UPDATE(ISHARP_LBA_PWL_SEG0, + ISHARP_LBA_PWL_SLOPE_SEG0, scl_data->dscl_prog_data.isharp_lba.slope_seg[0]); + REG_UPDATE(ISHARP_LBA_PWL_SEG1, + ISHARP_LBA_PWL_IN_SEG1, scl_data->dscl_prog_data.isharp_lba.in_seg[1]); + REG_UPDATE(ISHARP_LBA_PWL_SEG1, + ISHARP_LBA_PWL_BASE_SEG1, scl_data->dscl_prog_data.isharp_lba.base_seg[1]); + REG_UPDATE(ISHARP_LBA_PWL_SEG1, + ISHARP_LBA_PWL_SLOPE_SEG1, scl_data->dscl_prog_data.isharp_lba.slope_seg[1]); + REG_UPDATE(ISHARP_LBA_PWL_SEG2, + ISHARP_LBA_PWL_IN_SEG2, scl_data->dscl_prog_data.isharp_lba.in_seg[2]); + REG_UPDATE(ISHARP_LBA_PWL_SEG2, + ISHARP_LBA_PWL_BASE_SEG2, scl_data->dscl_prog_data.isharp_lba.base_seg[2]); + REG_UPDATE(ISHARP_LBA_PWL_SEG2, + ISHARP_LBA_PWL_SLOPE_SEG2, scl_data->dscl_prog_data.isharp_lba.slope_seg[2]); + REG_UPDATE(ISHARP_LBA_PWL_SEG3, + ISHARP_LBA_PWL_IN_SEG3, scl_data->dscl_prog_data.isharp_lba.in_seg[3]); + REG_UPDATE(ISHARP_LBA_PWL_SEG3, + ISHARP_LBA_PWL_BASE_SEG3, scl_data->dscl_prog_data.isharp_lba.base_seg[3]); + REG_UPDATE(ISHARP_LBA_PWL_SEG3, + ISHARP_LBA_PWL_SLOPE_SEG3, scl_data->dscl_prog_data.isharp_lba.slope_seg[3]); + REG_UPDATE(ISHARP_LBA_PWL_SEG4, + ISHARP_LBA_PWL_IN_SEG4, scl_data->dscl_prog_data.isharp_lba.in_seg[4]); + REG_UPDATE(ISHARP_LBA_PWL_SEG4, + ISHARP_LBA_PWL_BASE_SEG4, scl_data->dscl_prog_data.isharp_lba.base_seg[4]); + REG_UPDATE(ISHARP_LBA_PWL_SEG4, + ISHARP_LBA_PWL_SLOPE_SEG4, scl_data->dscl_prog_data.isharp_lba.slope_seg[4]); + REG_UPDATE(ISHARP_LBA_PWL_SEG5, + ISHARP_LBA_PWL_IN_SEG5, scl_data->dscl_prog_data.isharp_lba.in_seg[5]); + REG_UPDATE(ISHARP_LBA_PWL_SEG5, + ISHARP_LBA_PWL_BASE_SEG5, scl_data->dscl_prog_data.isharp_lba.base_seg[5]); + + /* ISHARP_FMT_MODE */ + REG_UPDATE(ISHARP_MODE, + ISHARP_FMT_MODE, scl_data->dscl_prog_data.isharp_fmt.mode); + /* ISHARP_FMT_NORM */ + REG_UPDATE(ISHARP_MODE, + ISHARP_FMT_NORM, scl_data->dscl_prog_data.isharp_fmt.norm); + /* ISHARP_DELTA_LUT */ + dpp401_dscl_set_isharp_filter(dpp, scl_data->dscl_prog_data.isharp_delta); + /* ISHARP_NLDELTA_SCLIP_EN_P */ + REG_UPDATE(ISHARP_NLDELTA_SOFT_CLIP, + ISHARP_NLDELTA_SCLIP_EN_P, scl_data->dscl_prog_data.isharp_nldelta_sclip.enable_p); + /* ISHARP_NLDELTA_SCLIP_PIVOT_P */ + REG_UPDATE(ISHARP_NLDELTA_SOFT_CLIP, + ISHARP_NLDELTA_SCLIP_PIVOT_P, scl_data->dscl_prog_data.isharp_nldelta_sclip.pivot_p); + /* ISHARP_NLDELTA_SCLIP_SLOPE_P */ + REG_UPDATE(ISHARP_NLDELTA_SOFT_CLIP, + ISHARP_NLDELTA_SCLIP_SLOPE_P, scl_data->dscl_prog_data.isharp_nldelta_sclip.slope_p); + /* ISHARP_NLDELTA_SCLIP_EN_N */ + REG_UPDATE(ISHARP_NLDELTA_SOFT_CLIP, + ISHARP_NLDELTA_SCLIP_EN_N, scl_data->dscl_prog_data.isharp_nldelta_sclip.enable_n); + /* ISHARP_NLDELTA_SCLIP_PIVOT_N */ + REG_UPDATE(ISHARP_NLDELTA_SOFT_CLIP, + ISHARP_NLDELTA_SCLIP_PIVOT_N, scl_data->dscl_prog_data.isharp_nldelta_sclip.pivot_n); + /* ISHARP_NLDELTA_SCLIP_SLOPE_N */ + REG_UPDATE(ISHARP_NLDELTA_SOFT_CLIP, + ISHARP_NLDELTA_SCLIP_SLOPE_N, scl_data->dscl_prog_data.isharp_nldelta_sclip.slope_n); + + /* Blur and Scale Coefficients - SCL_COEF_RAM_TAP_SELECT */ + if (scl_data->dscl_prog_data.isharp_en) { + if (scl_data->dscl_prog_data.filter_blur_scale_v) { + dpp401_dscl_set_scaler_filter( + dpp, scl_data->taps.v_taps, + SCL_COEF_VERTICAL_BLUR_SCALE, + scl_data->dscl_prog_data.filter_blur_scale_v); + } + if (scl_data->dscl_prog_data.filter_blur_scale_h) { + dpp401_dscl_set_scaler_filter( + dpp, scl_data->taps.h_taps, + SCL_COEF_HORIZONTAL_BLUR_SCALE, + scl_data->dscl_prog_data.filter_blur_scale_h); + } + } PERF_TRACE(); } // dpp401_dscl_program_isharp /** 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 a638c410e32a..c04c8b8f2114 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 @@ -387,6 +387,19 @@ bool dcn401_validate_bandwidth(struct dc *dc, 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_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) diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c index 82fbd2b59c70..2836f28fa3af 100644 --- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c +++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c @@ -913,6 +913,25 @@ static void spl_set_filters_data(struct dscl_prog_data *dscl_prog_data, dscl_prog_data->filter_v_c = spl_dscl_get_filter_coeffs_64p( data->taps.v_taps_c, data->ratios.vert_c); } + +static const uint16_t *spl_dscl_get_blur_scale_coeffs_64p(int taps) +{ + if ((taps == 3) || (taps == 4) || (taps == 6)) + return spl_get_filter_isharp_bs_4tap_64p(); + else { + /* should never happen, bug */ + return NULL; + } +} +static void spl_set_blur_scale_data(struct dscl_prog_data *dscl_prog_data, + const struct spl_scaler_data *data) +{ + dscl_prog_data->filter_blur_scale_h = spl_dscl_get_blur_scale_coeffs_64p( + data->taps.h_taps); + dscl_prog_data->filter_blur_scale_v = spl_dscl_get_blur_scale_coeffs_64p( + data->taps.v_taps); +} + /* Populate dscl prog data structure from scaler data calculated by SPL */ static void spl_set_dscl_prog_data(struct spl_in *spl_in, struct spl_out *spl_out) { @@ -1226,10 +1245,18 @@ static void spl_set_isharp_noise_det_mode(struct dscl_prog_data *dscl_prog_data) else if (dscl_prog_data->taps.h_taps == 3) dscl_prog_data->isharp_noise_det.mode = 0; // ISHARP_NOISEDET_MODE }; -/* Set EASF data */ +/* Set Sharpener data */ static void spl_set_isharp_data(struct dscl_prog_data *dscl_prog_data, - struct adaptive_sharpness adp_sharpness) + struct adaptive_sharpness adp_sharpness, bool enable_isharp, + enum linear_light_scaling lls_pref, enum spl_pixel_format format, + const struct spl_scaler_data *data) { + /* Turn off sharpener if not required */ + if (!enable_isharp) { + dscl_prog_data->isharp_en = 0; + return; + } + dscl_prog_data->isharp_en = 1; // ISHARP_EN dscl_prog_data->isharp_noise_det.enable = 1; // ISHARP_NOISEDET_EN // Set ISHARP_NOISEDET_MODE if htaps = 6-tap @@ -1243,7 +1270,11 @@ static void spl_set_isharp_data(struct dscl_prog_data *dscl_prog_data, dscl_prog_data->isharp_noise_det.pwl_end_in = 13; // ISHARP_NOISEDET_PWL_END_IN dscl_prog_data->isharp_noise_det.pwl_slope = 1623; // ISHARP_NOISEDET_PWL_SLOPE - dscl_prog_data->isharp_fmt.mode = 1; // ISHARP_FMT_MODE + if ((lls_pref == LLS_PREF_NO) && !spl_is_yuv420(format)) /* ISHARP_FMT_MODE */ + dscl_prog_data->isharp_fmt.mode = 1; + else + dscl_prog_data->isharp_fmt.mode = 0; + dscl_prog_data->isharp_fmt.norm = 0x3C00; // ISHARP_FMT_NORM dscl_prog_data->isharp_lba.mode = 0; // ISHARP_LBA_MODE // ISHARP_LBA_PWL_SEG0: ISHARP Local Brightness Adjustment PWL Segment 0 @@ -1269,7 +1300,7 @@ static void spl_set_isharp_data(struct dscl_prog_data *dscl_prog_data, // ISHARP_LBA_PWL_SEG5: ISHARP LBA PWL Segment 5 dscl_prog_data->isharp_lba.in_seg[5] = 1023; // ISHARP LBA PWL for Seg 5.INPUT value in U0.10 format dscl_prog_data->isharp_lba.base_seg[5] = 0; // ISHARP LBA PWL for Seg 5. BASE value in U0.6 format - switch (adp_sharpness.sharpness) { + switch (adp_sharpness.sharpness) { case SHARPNESS_LOW: dscl_prog_data->isharp_delta = spl_get_filter_isharp_1D_lut_0p5x(); break; @@ -1284,17 +1315,28 @@ static void spl_set_isharp_data(struct dscl_prog_data *dscl_prog_data, } // Program the nldelta soft clip values - dscl_prog_data->isharp_nldelta_sclip.enable_p = 1; // ISHARP_NLDELTA_SCLIP_EN_P - dscl_prog_data->isharp_nldelta_sclip.pivot_p = 70; // ISHARP_NLDELTA_SCLIP_PIVOT_P - dscl_prog_data->isharp_nldelta_sclip.slope_p = 24; // ISHARP_NLDELTA_SCLIP_SLOPE_P - dscl_prog_data->isharp_nldelta_sclip.enable_n = 1; // ISHARP_NLDELTA_SCLIP_EN_N - dscl_prog_data->isharp_nldelta_sclip.pivot_n = 70; // ISHARP_NLDELTA_SCLIP_PIVOT_N - dscl_prog_data->isharp_nldelta_sclip.slope_n = 24; // ISHARP_NLDELTA_SCLIP_SLOPE_N + if (lls_pref == LLS_PREF_YES) { + dscl_prog_data->isharp_nldelta_sclip.enable_p = 0; /* ISHARP_NLDELTA_SCLIP_EN_P */ + dscl_prog_data->isharp_nldelta_sclip.pivot_p = 0; /* ISHARP_NLDELTA_SCLIP_PIVOT_P */ + dscl_prog_data->isharp_nldelta_sclip.slope_p = 0; /* ISHARP_NLDELTA_SCLIP_SLOPE_P */ + dscl_prog_data->isharp_nldelta_sclip.enable_n = 1; /* ISHARP_NLDELTA_SCLIP_EN_N */ + dscl_prog_data->isharp_nldelta_sclip.pivot_n = 71; /* ISHARP_NLDELTA_SCLIP_PIVOT_N */ + dscl_prog_data->isharp_nldelta_sclip.slope_n = 16; /* ISHARP_NLDELTA_SCLIP_SLOPE_N */ + } else { + dscl_prog_data->isharp_nldelta_sclip.enable_p = 1; /* ISHARP_NLDELTA_SCLIP_EN_P */ + dscl_prog_data->isharp_nldelta_sclip.pivot_p = 70; /* ISHARP_NLDELTA_SCLIP_PIVOT_P */ + dscl_prog_data->isharp_nldelta_sclip.slope_p = 24; /* ISHARP_NLDELTA_SCLIP_SLOPE_P */ + dscl_prog_data->isharp_nldelta_sclip.enable_n = 1; /* ISHARP_NLDELTA_SCLIP_EN_N */ + dscl_prog_data->isharp_nldelta_sclip.pivot_n = 70; /* ISHARP_NLDELTA_SCLIP_PIVOT_N */ + dscl_prog_data->isharp_nldelta_sclip.slope_n = 24; /* ISHARP_NLDELTA_SCLIP_SLOPE_N */ + } // Set the values as per lookup table + spl_set_blur_scale_data(dscl_prog_data, data); } static bool spl_get_isharp_en(struct adaptive_sharpness adp_sharpness, - int vscale_ratio, int hscale_ratio, struct spl_taps taps) + int vscale_ratio, int hscale_ratio, struct spl_taps taps, + enum spl_pixel_format format) { bool enable_isharp = false; @@ -1307,6 +1349,10 @@ static bool spl_get_isharp_en(struct adaptive_sharpness adp_sharpness, } // Scaling is up to 1:1 (no scaling) or upscaling + /* Only apply sharpness to NV12 and not P010 */ + if (format != SPL_PIXEL_FORMAT_420BPP8) + return enable_isharp; + // LB support horizontal taps 4,6 or vertical taps 3, 4, 6 if (taps.h_taps == 4 || taps.h_taps == 6 || taps.v_taps == 3 || taps.v_taps == 4 || taps.v_taps == 6) { @@ -1342,13 +1388,14 @@ static bool spl_choose_lls_policy(enum spl_pixel_format format, return false; } -/* Caclulate scaler parameters */ +/* Calculate scaler parameters */ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out) { bool res = false; bool enable_easf_v = false; bool enable_easf_h = false; bool lls_enable_easf = true; + const struct spl_scaler_data *data = &spl_out->scl_data; // All SPL calls /* recout calculation */ /* depends on h_active */ @@ -1400,10 +1447,12 @@ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out) } // Set EASF spl_set_easf_data(spl_out->dscl_prog_data, enable_easf_v, enable_easf_h, spl_in->lls_pref, - spl_in->basic_in.format); // Set iSHARP + spl_in->basic_in.format); + // Set iSHARP bool enable_isharp = spl_get_isharp_en(spl_in->adaptive_sharpness, vratio, hratio, - spl_out->scl_data.taps); - if (enable_isharp) - spl_set_isharp_data(spl_out->dscl_prog_data, spl_in->adaptive_sharpness); + spl_out->scl_data.taps, spl_in->basic_in.format); + spl_set_isharp_data(spl_out->dscl_prog_data, spl_in->adaptive_sharpness, enable_isharp, + spl_in->lls_pref, spl_in->basic_in.format, data); + return res; } diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.c index 26b48b3576a5..8bc838c7c3c5 100644 --- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.c +++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.c @@ -241,7 +241,7 @@ static const uint32_t filter_isharp_1D_lut_2p0x[32] = { // LanczosEd // S1.10 //======================================================== -static const uint32_t filter_isharp_wide_6tap_64p[198] = { +static const uint16_t filter_isharp_wide_6tap_64p[198] = { 0x0000, 0x0000, 0x0400, 0x0000, 0x0000, 0x0000, 0x0003, 0x0FF3, 0x0400, 0x000D, 0x0FFD, 0x0000, 0x0006, 0x0FE7, 0x03FE, 0x001C, 0x0FF9, 0x0000, @@ -285,7 +285,7 @@ static const uint32_t filter_isharp_wide_6tap_64p[198] = { // Blur & Scale LPF // S1.10 //======================================================== -static const uint32_t filter_isharp_bs_4tap_64p[198] = { +static const uint16_t filter_isharp_bs_4tap_64p[198] = { 0x0000, 0x00E5, 0x0237, 0x00E4, 0x0000, 0x0000, 0x0000, 0x00DE, 0x0237, 0x00EB, 0x0000, 0x0000, 0x0000, 0x00D7, 0x0236, 0x00F2, 0x0001, 0x0000, @@ -340,11 +340,11 @@ const uint32_t *spl_get_filter_isharp_1D_lut_2p0x(void) { return filter_isharp_1D_lut_2p0x; } -const uint32_t *spl_get_filter_isharp_wide_6tap_64p(void) +const uint16_t *spl_get_filter_isharp_wide_6tap_64p(void) { return filter_isharp_wide_6tap_64p; } -const uint32_t *spl_get_filter_isharp_bs_4tap_64p(void) +const uint16_t *spl_get_filter_isharp_bs_4tap_64p(void) { return filter_isharp_bs_4tap_64p; } diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.h b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.h index ff189d86e534..1aaf4c50c1bc 100644 --- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.h +++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_isharp_filters.h @@ -12,6 +12,6 @@ const uint32_t *spl_get_filter_isharp_1D_lut_0p5x(void); const uint32_t *spl_get_filter_isharp_1D_lut_1p0x(void); const uint32_t *spl_get_filter_isharp_1D_lut_1p5x(void); const uint32_t *spl_get_filter_isharp_1D_lut_2p0x(void); -const uint32_t *spl_get_filter_isharp_bs_4tap_64p(void); -const uint32_t *spl_get_filter_isharp_wide_6tap_64p(void); +const uint16_t *spl_get_filter_isharp_bs_4tap_64p(void); +const uint16_t *spl_get_filter_isharp_wide_6tap_64p(void); #endif /* __DC_SPL_ISHARP_FILTERS_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h index 0c9edee0582e..a8f7fccfa16b 100644 --- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h +++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl_types.h @@ -393,6 +393,9 @@ struct dscl_prog_data { struct isharp_fmt isharp_fmt; // ISHARP_FMT const uint32_t *isharp_delta; struct isharp_nldelta_sclip isharp_nldelta_sclip; // ISHARP_NLDELTA_SCLIP + /* blur and scale filter */ + const uint16_t *filter_blur_scale_v; + const uint16_t *filter_blur_scale_h; }; /* SPL input and output definitions */ -- cgit From ddef2cfbb8927f7236f1e0d12ffd35b5d576e300 Mon Sep 17 00:00:00 2001 From: Rodrigo Siqueira Date: Tue, 14 May 2024 11:22:00 -0600 Subject: drm/amd/display: Remove unused code This commit removes some unused code with the required adjustments. Signed-off-by: Rodrigo Siqueira Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 - drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h | 2 +- drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 5 ----- drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c | 6 +----- 4 files changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 1055970d3888..31e3371b1b2e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1587,7 +1587,6 @@ struct dc_plane_state *dc_get_surface_for_mpcc(struct dc *dc, uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane); void dc_set_disable_128b_132b_stream_overhead(bool disable); -bool dc_get_disable_128b_132b_stream_overhead(void); /* The function returns minimum bandwidth required to drive a given timing * return - minimum required timing bandwidth in kbps. 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 1aaae7a5bd41..4bc85aaf17da 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 @@ -726,4 +726,4 @@ void dpp401_set_cursor_matrix( enum dc_color_space color_space, struct dc_csc_transform cursor_csc_color_matrix); -#endif +#endif /* __DCN401_DPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index b9d10e95ef7a..a1727e5bf024 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -1261,11 +1261,6 @@ void dc_set_disable_128b_132b_stream_overhead(bool disable) disable_128b_132b_stream_overhead = disable; } -bool dc_get_disable_128b_132b_stream_overhead(void) -{ - return disable_128b_132b_stream_overhead; -} - void dc_dsc_get_default_config_option(const struct dc *dc, struct dc_dsc_config_options *options) { options->dsc_min_slice_height_override = dc->debug.dsc_min_slice_height_override; 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 597817b51228..054607c944a3 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 @@ -880,12 +880,8 @@ static void dcn401_program_compbuf_segments(struct hubbub *hubbub, unsigned comp + 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; -#ifdef DIAGS_BUILD - REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &cur_compbuf_size_seg); - ASSERT(!cur_compbuf_size_seg); -#else + ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &cur_compbuf_size_seg) && !cur_compbuf_size_seg); -#endif } } -- cgit From 234e94555800d644ae970ff8da50f1f03dbc6ff9 Mon Sep 17 00:00:00 2001 From: Aurabindo Pillai Date: Tue, 21 May 2024 19:46:31 +0000 Subject: drm/amd/display: Enable copying of bounding box data from VBIOS DMUB Allocate some memory, send the address in chunks to dmub, and finally ask it to copy the bounding box data into the newly allocated memory. Signed-off-by: Aurabindo Pillai Acked-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 121 +++++++++++++++++++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 10 ++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 24 +--- drivers/gpu/drm/amd/display/dc/core/dc.c | 5 + drivers/gpu/drm/amd/display/dc/dc.h | 3 + .../dc/dml2/dml21/dml21_translation_helper.c | 6 +- drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h | 1 + 7 files changed, 146 insertions(+), 24 deletions(-) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') 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 6688b13d28e1..011981bee58c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1627,6 +1627,117 @@ static void retrieve_dmi_info(struct amdgpu_display_manager *dm) } } +void* +dm_allocate_gpu_mem( + struct amdgpu_device *adev, + enum dc_gpu_mem_alloc_type type, + size_t size, + long long *addr) +{ + struct dal_allocation *da; + u32 domain = (type == DC_MEM_ALLOC_TYPE_GART) ? + AMDGPU_GEM_DOMAIN_GTT : AMDGPU_GEM_DOMAIN_VRAM; + int ret; + + da = kzalloc(sizeof(struct dal_allocation), GFP_KERNEL); + if (!da) + return NULL; + + ret = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE, + domain, &da->bo, + &da->gpu_addr, &da->cpu_ptr); + + *addr = da->gpu_addr; + + if (ret) { + kfree(da); + return NULL; + } + + /* add da to list in dm */ + list_add(&da->list, &adev->dm.da_list); + + return da->cpu_ptr; +} + +static enum dmub_status +dm_dmub_send_vbios_gpint_command(struct amdgpu_device *adev, + enum dmub_gpint_command command_code, + uint16_t param, + uint32_t timeout_us) +{ + union dmub_gpint_data_register reg, test; + uint32_t i; + + /* Assume that VBIOS DMUB is ready to take commands */ + + reg.bits.status = 1; + reg.bits.command_code = command_code; + reg.bits.param = param; + + cgs_write_register(adev->dm.cgs_device, 0x34c0 + 0x01f8, reg.all); + + for (i = 0; i < timeout_us; ++i) { + udelay(1); + + /* Check if our GPINT got acked */ + reg.bits.status = 0; + test = (union dmub_gpint_data_register) + cgs_read_register(adev->dm.cgs_device, 0x34c0 + 0x01f8); + + if (test.all == reg.all) + return DMUB_STATUS_OK; + } + + return DMUB_STATUS_TIMEOUT; +} + +static struct dml2_soc_bb *dm_dmub_get_vbios_bounding_box(struct amdgpu_device *adev) +{ + struct dml2_soc_bb *bb; + long long addr; + int i = 0; + uint16_t chunk; + enum dmub_gpint_command send_addrs[] = { + DMUB_GPINT__SET_BB_ADDR_WORD0, + DMUB_GPINT__SET_BB_ADDR_WORD1, + DMUB_GPINT__SET_BB_ADDR_WORD2, + DMUB_GPINT__SET_BB_ADDR_WORD3, + }; + enum dmub_status ret; + + switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) { + case IP_VERSION(4, 0, 1): + break; + default: + return NULL; + } + + bb = dm_allocate_gpu_mem(adev, + DC_MEM_ALLOC_TYPE_GART, + sizeof(struct dml2_soc_bb), + &addr); + if (!bb) + return NULL; + + for (i = 0; i < 4; i++) { + /* Extract 16-bit chunk */ + chunk = ((uint64_t) addr >> (i * 16)) & 0xFFFF; + /* Send the chunk */ + ret = dm_dmub_send_vbios_gpint_command(adev, send_addrs[i], chunk, 30000); + if (ret != DMUB_STATUS_OK) + /* No need to free bb here since it shall be done unconditionally */ + return NULL; + } + + /* Now ask DMUB to copy the bb */ + ret = dm_dmub_send_vbios_gpint_command(adev, DMUB_GPINT__BB_COPY, 1, 200000); + if (ret != DMUB_STATUS_OK) + return NULL; + + return bb; +} + static int amdgpu_dm_init(struct amdgpu_device *adev) { struct dc_init_data init_data; @@ -1748,6 +1859,11 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) retrieve_dmi_info(&adev->dm); + if (adev->dm.bb_from_dmub) + init_data.bb_from_dmub = adev->dm.bb_from_dmub; + else + init_data.bb_from_dmub = NULL; + /* Display Core create. */ adev->dm.dc = dc_create(&init_data); @@ -2305,6 +2421,8 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) return -EINVAL; } + adev->dm.bb_from_dmub = dm_dmub_get_vbios_bounding_box(adev); + return 0; } @@ -2334,6 +2452,9 @@ static int dm_sw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + kfree(adev->dm.bb_from_dmub); + adev->dm.bb_from_dmub = NULL; + kfree(adev->dm.dmub_fb_info); adev->dm.dmub_fb_info = NULL; 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 a01f3f5bf2c0..94fc4c15d2db 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -578,6 +578,11 @@ struct amdgpu_display_manager { * Guards access to DPIA AUX */ struct mutex dpia_aux_lock; + + /* + * Bounding box data read from dmub during early initialization for DCN4+ + */ + struct dml2_soc_bb *bb_from_dmub; }; enum dsc_clock_force_state { @@ -964,4 +969,9 @@ amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state, int convert_dc_color_depth_into_bpc(enum dc_color_depth display_color_depth); struct idle_workqueue *idle_create_workqueue(struct amdgpu_device *adev); + +void *dm_allocate_gpu_mem(struct amdgpu_device *adev, + enum dc_gpu_mem_alloc_type type, + size_t size, + long long *addr); #endif /* __AMDGPU_DM_H__ */ 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 6d0f78b9ec0c..8eb2f10f2c38 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 @@ -1045,30 +1045,8 @@ void *dm_helpers_allocate_gpu_mem( long long *addr) { struct amdgpu_device *adev = ctx->driver_context; - struct dal_allocation *da; - u32 domain = (type == DC_MEM_ALLOC_TYPE_GART) ? - AMDGPU_GEM_DOMAIN_GTT : AMDGPU_GEM_DOMAIN_VRAM; - int ret; - - da = kzalloc(sizeof(struct dal_allocation), GFP_KERNEL); - if (!da) - return NULL; - - ret = amdgpu_bo_create_kernel(adev, size, PAGE_SIZE, - domain, &da->bo, - &da->gpu_addr, &da->cpu_ptr); - - *addr = da->gpu_addr; - - if (ret) { - kfree(da); - return NULL; - } - - /* add da to list in dm */ - list_add(&da->list, &adev->dm.da_list); - return da->cpu_ptr; + return dm_allocate_gpu_mem(adev, type, size, addr); } void dm_helpers_free_gpu_mem( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 4612c60edebd..0d97611c4817 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1014,6 +1014,11 @@ static bool dc_construct(struct dc *dc, dc->dcn_ip = dcn_ip; + if (init_params->bb_from_dmub) + dc->dml2_options.bb_from_dmub = init_params->bb_from_dmub; + else + dc->dml2_options.bb_from_dmub = NULL; + if (!dc_construct_ctx(dc, init_params)) { dm_error("%s: failed to create ctx\n", __func__); goto fail; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 31e3371b1b2e..d0ed01ac460d 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1067,6 +1067,8 @@ struct dchub_init_data { bool dchub_info_valid; }; +struct dml2_soc_bb; + struct dc_init_data { struct hw_asic_id asic_id; void *driver; /* ctx */ @@ -1099,6 +1101,7 @@ struct dc_init_data { uint32_t *dcn_reg_offsets; uint32_t *nbio_reg_offsets; uint32_t *clk_reg_offsets; + struct dml2_soc_bb *bb_from_dmub; }; struct dc_callback_init { diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c index 37998f2c0b14..9f641ffdc924 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c @@ -26,7 +26,11 @@ static void dml21_init_socbb_params(struct dml2_initialize_instance_in_out *dml_ break; case DCN_VERSION_4_01: default: - soc_bb = &dml2_socbb_dcn401; + if (config->bb_from_dmub) + soc_bb = config->bb_from_dmub; + else + soc_bb = &dml2_socbb_dcn401; + qos_params = &dml_dcn401_soc_qos_params; } diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h index dcb4e6f4d916..20b3970c0857 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h @@ -236,6 +236,7 @@ struct dml2_configuration_options { bool use_clock_dc_limits; bool gpuvm_enable; + struct dml2_soc_bb *bb_from_dmub; }; /* -- cgit From e902dd7f3e3b93a401e1d3c0322cce933e75e809 Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Mon, 13 May 2024 18:14:59 -0400 Subject: drm/amd/display: workaround for oled eDP not lighting up on DCN401 [Why] Currently there's an issue on DCN401 that prevents oled eDP panels from being lit up that is still under investigation. To unblock dev work while investigating, we can work around the issue by skipping toggling the enablement of the backlight. [How] - new debug bit that will skip touching backlight enable DPCD for oled Reviewed-by: Alvin Lee Reviewed-by: Wenjing Liu Acked-by: Zaeem Mohamed Signed-off-by: Joshua Aberback Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c | 3 +++ drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c | 1 + 3 files changed, 5 insertions(+) (limited to 'drivers/gpu/drm/amd/display/dc/dc.h') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d0ed01ac460d..a06015165a61 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1042,6 +1042,7 @@ struct dc_debug_options { unsigned int force_easf; unsigned int force_sharpness; unsigned int force_lls; + bool edp_oled_no_backlight_enable; }; 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 ad9aca790dd7..89f66d88c3b0 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 @@ -248,6 +248,9 @@ bool edp_backlight_enable_aux(struct dc_link *link, bool enable) link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) return false; + if (link->dc->debug.edp_oled_no_backlight_enable && link->dpcd_sink_ext_caps.bits.oled) + return true; + if (core_link_write_dpcd(link, DP_SOURCE_BACKLIGHT_ENABLE, &backlight_enable, 1) != DC_OK) return false; 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 8dfb0a3d21cb..49a8d7048194 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 @@ -732,6 +732,7 @@ static const struct dc_debug_options debug_defaults_drv = { }, .force_cositing = CHROMA_COSITING_TOPLEFT + 1, .disable_idle_power_optimizations = true, + .edp_oled_no_backlight_enable = true, }; static struct dce_aux *dcn401_aux_engine_create( -- cgit