Commit 21e471f0 authored by Eric Yang's avatar Eric Yang Committed by Alex Deucher
Browse files

drm/amd/display: Set dispclk and dprefclock directly



[Why]
To simply logic for setting DCN specific clocks, we will send
SMU message directly through the VBIOS message box.

[How]
Add new structure in pp_smu to hold functions to set clocks
through vbios message box

Signed-off-by: default avatarEric Yang <Eric.Yang2@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 4cd75ff0
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -297,7 +297,7 @@ void generic_reg_wait(const struct dc_context *ctx,
	int i;

	/* something is terribly wrong if time out is > 200ms. (5Hz) */
	ASSERT(delay_between_poll_us * time_out_num_tries <= 200000);
	ASSERT(delay_between_poll_us * time_out_num_tries <= 3000000);

	for (i = 0; i <= time_out_num_tries; i++) {
		if (i) {
+4 −4
Original line number Diff line number Diff line
@@ -782,22 +782,22 @@ static void dce12_update_clocks(struct clk_mgr *clk_mgr,
	dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context);
}

static const struct clk_mgr_funcs dce120_funcs = {
static struct clk_mgr_funcs dce120_funcs = {
	.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
	.update_clocks = dce12_update_clocks
};

static const struct clk_mgr_funcs dce112_funcs = {
static struct clk_mgr_funcs dce112_funcs = {
	.get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz,
	.update_clocks = dce112_update_clocks
};

static const struct clk_mgr_funcs dce110_funcs = {
static struct clk_mgr_funcs dce110_funcs = {
	.get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz,
	.update_clocks = dce11_update_clocks,
};

static const struct clk_mgr_funcs dce_funcs = {
static struct clk_mgr_funcs dce_funcs = {
	.get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz,
	.update_clocks = dce_update_clocks
};
+21 −0
Original line number Diff line number Diff line
@@ -39,6 +39,11 @@
#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_SF(reg_name, field_name, post_fix)\
	.field_name = reg_name ## __ ## field_name ## post_fix

@@ -50,23 +55,39 @@
	CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\
	CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh)

#define CLK_MASK_SH_LIST_RV1(mask_sh) \
	CLK_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(mask_sh),\
	CLK_SF(MP1_SMN_C2PMSG_67, CONTENT, mask_sh),\
	CLK_SF(MP1_SMN_C2PMSG_83, CONTENT, mask_sh),\
	CLK_SF(MP1_SMN_C2PMSG_91, CONTENT, mask_sh),


#define CLK_REG_FIELD_LIST(type) \
	type DPREFCLK_SRC_SEL; \
	type DENTIST_DPREFCLK_WDIVIDER; \
	type DENTIST_DISPCLK_WDIVIDER; \
	type DENTIST_DISPCLK_CHG_DONE;

#define VBIOS_SMU_REG_FIELD_LIST(type) \
	type CONTENT;

struct clk_mgr_shift {
	CLK_REG_FIELD_LIST(uint8_t)
	VBIOS_SMU_REG_FIELD_LIST(uint32_t)
};

struct clk_mgr_mask {
	CLK_REG_FIELD_LIST(uint32_t)
	VBIOS_SMU_REG_FIELD_LIST(uint32_t)
};

struct clk_mgr_registers {
	uint32_t DPREFCLK_CNTL;
	uint32_t DENTIST_DISPCLK_CNTL;

	uint32_t MP1_SMN_C2PMSG_67;
	uint32_t MP1_SMN_C2PMSG_83;
	uint32_t MP1_SMN_C2PMSG_91;
};

struct state_dependent_clocks {
+72 −6
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@

#include "reg_helper.h"
#include "core_types.h"
#include "dal_asic_id.h"

#define TO_DCE_CLK_MGR(clocks)\
	container_of(clocks, struct dce_clk_mgr, base)
@@ -91,12 +92,17 @@ static int dcn1_determine_dppclk_threshold(struct clk_mgr *clk_mgr, struct dc_cl

static void dcn1_ramp_up_dispclk_with_dpp(struct clk_mgr *clk_mgr, struct dc_clocks *new_clocks)
{
	int i;
	struct dc *dc = clk_mgr->ctx->dc;
	int dispclk_to_dpp_threshold = dcn1_determine_dppclk_threshold(clk_mgr, new_clocks);
	bool request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz;
	int i;

	/* set disp clk to dpp clk threshold */

	if (clk_mgr->funcs->set_dispclk && clk_mgr->funcs->set_dprefclk) {
		clk_mgr->funcs->set_dispclk(clk_mgr, dispclk_to_dpp_threshold);
		clk_mgr->funcs->set_dprefclk(clk_mgr);
	} else
		dce112_set_clock(clk_mgr, dispclk_to_dpp_threshold);

	/* update request dpp clk division option */
@@ -113,8 +119,13 @@ static void dcn1_ramp_up_dispclk_with_dpp(struct clk_mgr *clk_mgr, struct dc_clo
	}

	/* If target clk not same as dppclk threshold, set to target clock */
	if (dispclk_to_dpp_threshold != new_clocks->dispclk_khz)
		dce112_set_clock(clk_mgr, new_clocks->dispclk_khz);
	if (dispclk_to_dpp_threshold != new_clocks->dispclk_khz) {
		if (clk_mgr->funcs->set_dispclk && clk_mgr->funcs->set_dprefclk) {
			clk_mgr->funcs->set_dispclk(clk_mgr, new_clocks->dispclk_khz);
			clk_mgr->funcs->set_dprefclk(clk_mgr);
		} else
			dce112_set_clock(clk_mgr, dispclk_to_dpp_threshold);
	}

	clk_mgr->clks.dispclk_khz = new_clocks->dispclk_khz;
	clk_mgr->clks.dppclk_khz = new_clocks->dppclk_khz;
@@ -242,7 +253,62 @@ static void dcn1_update_clocks(struct clk_mgr *clk_mgr,
		}
	}
}
static const struct clk_mgr_funcs dcn1_funcs = {

#define VBIOSSMC_MSG_SetDispclkFreq           0x4
#define VBIOSSMC_MSG_SetDprefclkFreq          0x5

int dcn10_set_dispclk(struct clk_mgr *clk_mgr_base, int requested_dispclk_khz)
{
	int actual_dispclk_set_khz = -1;
	struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr_base);

	/* First clear response register */
	//dm_write_reg(ctx, mmMP1_SMN_C2PMSG_91, 0);
	REG_WRITE(MP1_SMN_C2PMSG_91, 0);

	/* Set the parameter register for the SMU message, unit is Mhz */
	//dm_write_reg(ctx, mmMP1_SMN_C2PMSG_83, requested_dispclk_khz / 1000);
	REG_WRITE(MP1_SMN_C2PMSG_83, requested_dispclk_khz / 1000);

	/* Trigger the message transaction by writing the message ID */
	//dm_write_reg(ctx, mmMP1_SMN_C2PMSG_67, VBIOSSMC_MSG_SetDispclkFreq);
	REG_WRITE(MP1_SMN_C2PMSG_67, VBIOSSMC_MSG_SetDispclkFreq);

	REG_WAIT(MP1_SMN_C2PMSG_91, CONTENT, 1, 10, 200000);

	/* Actual dispclk set is returned in the parameter register */
	actual_dispclk_set_khz = REG_READ(MP1_SMN_C2PMSG_83) * 1000;

	return actual_dispclk_set_khz;

}

int dcn10_set_dprefclk(struct clk_mgr *clk_mgr_base)
{
	int actual_dprefclk_set_khz = -1;
	struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr_base);

	REG_WRITE(MP1_SMN_C2PMSG_91, 0);

	/* Set the parameter register for the SMU message */
	REG_WRITE(MP1_SMN_C2PMSG_83, clk_mgr_dce->dprefclk_khz / 1000);

	/* Trigger the message transaction by writing the message ID */
	REG_WRITE(MP1_SMN_C2PMSG_67, VBIOSSMC_MSG_SetDprefclkFreq);

	/* Wait for SMU response */
	REG_WAIT(MP1_SMN_C2PMSG_91, CONTENT, 1, 10, 200000);

	actual_dprefclk_set_khz = REG_READ(MP1_SMN_C2PMSG_83) * 1000;

	return actual_dprefclk_set_khz;
}

int (*set_dispclk)(struct pp_smu *pp_smu, int dispclk);

int (*set_dprefclk)(struct pp_smu *pp_smu);

static struct clk_mgr_funcs dcn1_funcs = {
	.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
	.update_clocks = dcn1_update_clocks
};
@@ -266,8 +332,8 @@ struct clk_mgr *dcn1_clk_mgr_create(struct dc_context *ctx)
	clk_mgr_dce->dprefclk_ss_percentage = 0;
	clk_mgr_dce->dprefclk_ss_divider = 1000;
	clk_mgr_dce->ss_on_dprefclk = false;

	clk_mgr_dce->dprefclk_khz = 600000;

	if (bp->integrated_info)
		clk_mgr_dce->dentist_vco_freq_khz = bp->integrated_info->dentist_vco_freq;
	if (clk_mgr_dce->dentist_vco_freq_khz == 0) {
+28 −9
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@
#include "resource.h"
#include "include/irq_service_interface.h"
#include "dcn10_resource.h"

#include "dcn10_ipp.h"
#include "dcn10_mpc.h"
#include "irq/dcn10/irq_service_dcn10.h"
@@ -445,7 +444,6 @@ static const struct bios_registers bios_regs = {
	HUBP_REG_LIST_DCN10(id)\
}


static const struct dcn_mi_registers hubp_regs[] = {
	hubp_regs(0),
	hubp_regs(1),
@@ -461,7 +459,6 @@ static const struct dcn_mi_mask hubp_mask = {
		HUBP_MASK_SH_LIST_DCN10(_MASK)
};


static const struct dcn_hubbub_registers hubbub_reg = {
		HUBBUB_REG_LIST_DCN10(0)
};
@@ -494,6 +491,27 @@ static const struct dce110_clk_src_mask cs_mask = {
		CS_COMMON_MASK_SH_LIST_DCN1_0(_MASK)
};


#define mmMP1_SMN_C2PMSG_91            0x1629B
#define mmMP1_SMN_C2PMSG_83            0x16293
#define mmMP1_SMN_C2PMSG_67            0x16283

#define MP1_SMN_C2PMSG_91__CONTENT_MASK                    0xffffffffL
#define MP1_SMN_C2PMSG_83__CONTENT_MASK                    0xffffffffL
#define MP1_SMN_C2PMSG_67__CONTENT_MASK                    0xffffffffL
#define	MP1_SMN_C2PMSG_91__CONTENT__SHIFT                  0x00000000
#define	MP1_SMN_C2PMSG_83__CONTENT__SHIFT                  0x00000000
#define	MP1_SMN_C2PMSG_67__CONTENT__SHIFT                  0x00000000


static const struct clk_mgr_shift clk_mgr_shift = {
		CLK_MASK_SH_LIST_RV1(__SHIFT)
};

static const struct clk_mgr_mask clk_mgr_mask = {
		CLK_MASK_SH_LIST_RV1(_MASK)
};

static const struct resource_caps res_cap = {
		.num_timing_generator = 4,
		.num_opp = 4,
@@ -1343,12 +1361,6 @@ static bool construct(
			goto fail;
		}
	}
	pool->base.clk_mgr = dcn1_clk_mgr_create(ctx);
	if (pool->base.clk_mgr == NULL) {
		dm_error("DC: failed to create display clock!\n");
		BREAK_TO_DEBUGGER();
		goto fail;
	}

	pool->base.dmcu = dcn10_dmcu_create(ctx,
			&dmcu_regs,
@@ -1410,6 +1422,13 @@ static bool construct(

	pool->base.pp_smu = dcn10_pp_smu_create(ctx);

	pool->base.clk_mgr = dcn1_clk_mgr_create(ctx);
	if (pool->base.clk_mgr == NULL) {
		dm_error("DC: failed to create display clock!\n");
		BREAK_TO_DEBUGGER();
		goto fail;
	}

	if (!dc->debug.disable_pplib_clock_request)
		dcn_bw_update_from_pplib(dc);
	dcn_bw_sync_calcs_and_dml(dc);
Loading