Commit 12a6e62b authored by Alvin Lee's avatar Alvin Lee Committed by Alex Deucher
Browse files

drm/amd/display: Enable dc mode clock switching for DCN32x



- DC mode clock switch interface was previously only executed
  for DCN303. Enable it for DCN32x so that the interface is called
  correctly
- Assign function pointers for DCN32x that are used in the dc mode
  interface
- Update the dc mode interface to work generically for each ASIC
- In update_clocks, make sure to consider softmax if we're in DC mode

Reviewed-by: default avatarJun Lei <jun.lei@amd.com>
Acked-by: default avatarHamza Mahfooz <hamza.mahfooz@amd.com>
Signed-off-by: default avatarAlvin Lee <alvin.lee2@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ed83fe2a
Loading
Loading
Loading
Loading
+37 −6
Original line number Diff line number Diff line
@@ -541,9 +541,18 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
			clk_mgr_base->clks.p_state_change_support = p_state_change_support;

			/* to disable P-State switching, set UCLK min = max */
			if (!clk_mgr_base->clks.p_state_change_support)
			if (!clk_mgr_base->clks.p_state_change_support) {
				if (dc->clk_mgr->dc_mode_softmax_enabled) {
					/* On DCN32x we will never have the functional UCLK min above the softmax
					 * since we calculate mode support based on softmax being the max UCLK
					 * frequency.
					 */
					dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
						clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels - 1].memclk_mhz);
							dc->clk_mgr->bw_params->dc_mode_softmax_memclk);
				} else {
					dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz);
				}
			}
		}

		/* Always update saved value, even if new value not set due to P-State switching unsupported. Also check safe_to_lower for FCLK */
@@ -808,8 +817,7 @@ static void dcn32_set_hard_max_memclk(struct clk_mgr *clk_mgr_base)
	if (!clk_mgr->smu_present)
		return;

	dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK,
			clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels - 1].memclk_mhz);
	dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, clk_mgr_base->bw_params->max_memclk_mhz);
}

/* Get current memclk states, update bounding box */
@@ -827,6 +835,7 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
			&clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz,
			&num_entries_per_clk->num_memclk_levels);
	clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_UCLK);
	clk_mgr_base->bw_params->dc_mode_softmax_memclk = clk_mgr_base->bw_params->dc_mode_limit.memclk_mhz;

	/* memclk must have at least one level */
	num_entries_per_clk->num_memclk_levels = num_entries_per_clk->num_memclk_levels ? num_entries_per_clk->num_memclk_levels : 1;
@@ -841,7 +850,8 @@ static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
	} else {
		num_levels = num_entries_per_clk->num_fclk_levels;
	}

	clk_mgr_base->bw_params->max_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->clk_table.num_entries = num_levels ? num_levels : 1;

	if (clk_mgr->dpm_present && !num_levels)
@@ -894,6 +904,25 @@ static bool dcn32_is_smu_present(struct clk_mgr *clk_mgr_base)
	return clk_mgr->smu_present;
}

static void dcn32_set_max_memclk(struct clk_mgr *clk_mgr_base, unsigned int memclk_mhz)
{
	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);

	if (!clk_mgr->smu_present)
		return;

	dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, memclk_mhz);
}

static void dcn32_set_min_memclk(struct clk_mgr *clk_mgr_base, unsigned int memclk_mhz)
{
	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);

	if (!clk_mgr->smu_present)
		return;

	dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, memclk_mhz);
}

static struct clk_mgr_funcs dcn32_funcs = {
		.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
@@ -904,6 +933,8 @@ static struct clk_mgr_funcs dcn32_funcs = {
		.notify_wm_ranges = dcn32_notify_wm_ranges,
		.set_hard_min_memclk = dcn32_set_hard_min_memclk,
		.set_hard_max_memclk = dcn32_set_hard_max_memclk,
		.set_max_memclk = dcn32_set_max_memclk,
		.set_min_memclk = dcn32_set_min_memclk,
		.get_memclk_states_from_smu = dcn32_get_memclk_states_from_smu,
		.are_clock_states_equal = dcn32_are_clock_states_equal,
		.enable_pme_wa = dcn32_enable_pme_wa,
+6 −4
Original line number Diff line number Diff line
@@ -4763,15 +4763,17 @@ static void blank_and_force_memclk(struct dc *dc, bool apply, unsigned int memcl
 */
void dc_enable_dcmode_clk_limit(struct dc *dc, bool enable)
{
	uint32_t hw_internal_rev = dc->ctx->asic_id.hw_internal_rev;
	unsigned int softMax, maxDPM, funcMin;
	unsigned int softMax = 0, maxDPM = 0, funcMin = 0, i;
	bool p_state_change_support;

	if (!ASICREV_IS_BEIGE_GOBY_P(hw_internal_rev))
	if (!dc->config.dc_mode_clk_limit_support)
		return;

	softMax = dc->clk_mgr->bw_params->dc_mode_softmax_memclk;
	maxDPM = dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz;
	for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries; i++) {
		if (dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz > maxDPM)
			maxDPM = dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz;
	}
	funcMin = (dc->clk_mgr->clks.dramclk_khz + 999) / 1000;
	p_state_change_support = dc->clk_mgr->clks.p_state_change_support;

+1 −1
Original line number Diff line number Diff line
@@ -416,7 +416,7 @@ struct dc_config {
	uint8_t force_bios_fixed_vs;
	int sdpif_request_limit_words_per_umc;
	bool use_old_fixed_vs_sequence;
	bool disable_subvp_drr;
	bool dc_mode_clk_limit_support;
};

enum visual_confirm {
+1 −0
Original line number Diff line number Diff line
@@ -1190,6 +1190,7 @@ static bool dcn303_resource_construct(

	dc->caps.dp_hdmi21_pcon_support = true;

	dc->config.dc_mode_clk_limit_support = true;
	/* read VBIOS LTTPR caps */
	if (ctx->dc_bios->funcs->get_lttpr_caps) {
		enum bp_result bp_query_result;
+1 −0
Original line number Diff line number Diff line
@@ -179,6 +179,7 @@ static struct hubp_funcs dcn32_hubp_funcs = {
	.hubp_setup_interdependent = hubp2_setup_interdependent,
	.hubp_set_vm_system_aperture_settings = hubp3_set_vm_system_aperture_settings,
	.set_blank = hubp2_set_blank,
	.set_blank_regs = hubp2_set_blank_regs,
	.dcc_control = hubp3_dcc_control,
	.mem_program_viewport = min_set_viewport,
	.set_cursor_attributes	= hubp32_cursor_set_attributes,
Loading