Commit b486bc9e authored by Dillon Varone's avatar Dillon Varone Committed by Alex Deucher
Browse files

drm/amd/display: Add new message for DF throttling optimization on dcn401



[WHY]
When effective bandwidth from the SoC is enough to perform SubVP
prefetchs, then DF throttling is not required.

[HOW]
Provide SMU the required clocks for which DF throttling is not required.

Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: default avatarAlvin Lee <alvin.lee2@amd.com>
Signed-off-by: default avatarDillon Varone <dillon.varone@amd.com>
Signed-off-by: default avatarRodrigo Siqueira <rodrigo.siqueira@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent be4e3509
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -141,6 +141,20 @@ static bool dcn401_is_ppclk_idle_dpm_enabled(struct clk_mgr_internal *clk_mgr, P
	return ppclk_idle_dpm_enabled;
}

static bool dcn401_is_df_throttle_opt_enabled(struct clk_mgr_internal *clk_mgr)
{
	bool is_df_throttle_opt_enabled = false;

	if (ASICREV_IS_GC_12_0_1_A0(clk_mgr->base.ctx->asic_id.hw_internal_rev) &&
			clk_mgr->smu_ver >= 0x663500) {
		is_df_throttle_opt_enabled = !clk_mgr->base.ctx->dc->debug.force_subvp_df_throttle;
	}

	is_df_throttle_opt_enabled &= clk_mgr->smu_present;

	return is_df_throttle_opt_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)
@@ -869,6 +883,12 @@ static void dcn401_execute_block_sequence(struct clk_mgr *clk_mgr_base, unsigned
					params->update_idle_hardmin_params.uclk_mhz,
					params->update_idle_hardmin_params.fclk_mhz);
			break;
		case CLK_MGR401_UPDATE_SUBVP_HARDMINS:
			dcn401_smu_set_subvp_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,
@@ -945,15 +965,21 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
	bool update_active_uclk = false;
	bool update_idle_fclk = false;
	bool update_idle_uclk = false;
	bool update_subvp_prefetch_dramclk = false;
	bool update_subvp_prefetch_fclk = 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);
	bool is_df_throttle_opt_enabled = is_idle_dpm_enabled &&
		dcn401_is_df_throttle_opt_enabled(clk_mgr_internal);
	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 subvp_prefetch_dramclk_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.subvp_prefetch_dramclk_khz);
	int subvp_prefetch_fclk_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.subvp_prefetch_fclk_khz);

	unsigned int num_steps = 0;

@@ -1109,6 +1135,12 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
		}
	}

	if (should_set_clock(safe_to_lower, new_clocks->subvp_prefetch_dramclk_khz, clk_mgr_base->clks.subvp_prefetch_dramclk_khz)) {
		clk_mgr_base->clks.subvp_prefetch_dramclk_khz = new_clocks->subvp_prefetch_dramclk_khz;
		update_subvp_prefetch_dramclk = true;
		subvp_prefetch_dramclk_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.subvp_prefetch_dramclk_khz);
	}

	/* 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)) {
@@ -1129,6 +1161,12 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
		}
	}

	if (should_set_clock(safe_to_lower, new_clocks->subvp_prefetch_fclk_khz, clk_mgr_base->clks.subvp_prefetch_fclk_khz)) {
		clk_mgr_base->clks.subvp_prefetch_fclk_khz = new_clocks->subvp_prefetch_fclk_khz;
		update_subvp_prefetch_fclk = true;
		subvp_prefetch_fclk_mhz = khz_to_mhz_ceil(clk_mgr_base->clks.subvp_prefetch_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) {
@@ -1146,6 +1184,14 @@ static unsigned int dcn401_build_update_bandwidth_clocks_sequence(
		num_steps++;
	}

	/* CLK_MGR401_UPDATE_SUBVP_HARDMINS */
	if ((update_subvp_prefetch_dramclk || update_subvp_prefetch_fclk) && is_df_throttle_opt_enabled) {
		block_sequence[num_steps].params.update_idle_hardmin_params.uclk_mhz = subvp_prefetch_dramclk_mhz;
		block_sequence[num_steps].params.update_idle_hardmin_params.fclk_mhz = subvp_prefetch_fclk_mhz;
		block_sequence[num_steps].func = CLK_MGR401_UPDATE_SUBVP_HARDMINS;
		num_steps++;
	}

	/* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */
	if (update_active_uclk || update_idle_uclk) {
		if (!is_idle_dpm_enabled) {
+1 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ enum dcn401_clk_mgr_block_sequence_func {
	CLK_MGR401_UPDATE_DTBCLK_DTO,
	CLK_MGR401_UPDATE_DENTIST,
	CLK_MGR401_UPDATE_PSR_WAIT_LOOP,
	CLK_MGR401_UPDATE_SUBVP_HARDMINS,
};

struct dcn401_clk_mgr_block_sequence {
+23 −0
Original line number Diff line number Diff line
@@ -21,6 +21,11 @@

#define smu_print(str, ...) {DC_LOG_SMU(str, ##__VA_ARGS__); }

/* temporary define */
#ifndef DALSMC_MSG_SubvpUclkFclk
#define DALSMC_MSG_SubvpUclkFclk 0x1B
#endif

/*
 * Function to be used instead of REG_WAIT macro because the wait ends when
 * the register is NOT EQUAL to zero, and because the translation in msg_if.h
@@ -296,6 +301,24 @@ bool dcn401_smu_set_active_uclk_fclk_hardmin(struct clk_mgr_internal *clk_mgr,
	return success;
}

bool dcn401_smu_set_subvp_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_SubvpUclkFclk, param, &response);

	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);
+3 −0
Original line number Diff line number Diff line
@@ -23,6 +23,9 @@ bool dcn401_smu_set_idle_uclk_fclk_hardmin(struct clk_mgr_internal *clk_mgr,
bool dcn401_smu_set_active_uclk_fclk_hardmin(struct clk_mgr_internal *clk_mgr,
		uint16_t uclk_freq_mhz,
		uint16_t fclk_freq_mhz);
bool dcn401_smu_set_subvp_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);

+3 −0
Original line number Diff line number Diff line
@@ -629,6 +629,8 @@ struct dc_clocks {
	int bw_dispclk_khz;
	int idle_dramclk_khz;
	int idle_fclk_khz;
	int subvp_prefetch_dramclk_khz;
	int subvp_prefetch_fclk_khz;
};

struct dc_bw_validation_profile {
@@ -1072,6 +1074,7 @@ struct dc_debug_options {
	bool skip_full_updated_if_possible;
	unsigned int enable_oled_edp_power_up_opt;
	bool enable_hblank_borrow;
	bool force_subvp_df_throttle;
};


Loading