Commit 622a88c8 authored by Eric Yang's avatar Eric Yang Committed by Alex Deucher
Browse files

drm/amd/display: move wm ranges reporting to end of init hw



[Why]
SMU does not keep the wm table across S3, S4, need to re-send
the table. Also defer sending the cable to after DCN bave initialized

[How]
Send table at end of init hw

Signed-off-by: default avatarEric Yang <Eric.Yang2@amd.com>
Reviewed-by: default avatarYongqiang Sun <yongqiang.sun@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 0460f9ab
Loading
Loading
Loading
Loading
+76 −73
Original line number Diff line number Diff line
@@ -396,12 +396,87 @@ void rn_init_clocks(struct clk_mgr *clk_mgr)
	clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN;
}

void build_watermark_ranges(struct clk_bw_params *bw_params, struct pp_smu_wm_range_sets *ranges)
{
	int i, num_valid_sets;

	num_valid_sets = 0;

	for (i = 0; i < WM_SET_COUNT; i++) {
		/* skip empty entries, the smu array has no holes*/
		if (!bw_params->wm_table.entries[i].valid)
			continue;

		ranges->reader_wm_sets[num_valid_sets].wm_inst = bw_params->wm_table.entries[i].wm_inst;
		ranges->reader_wm_sets[num_valid_sets].wm_type = bw_params->wm_table.entries[i].wm_type;;
		/* We will not select WM based on dcfclk, so leave it as unconstrained */
		ranges->reader_wm_sets[num_valid_sets].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
		ranges->reader_wm_sets[num_valid_sets].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
		/* fclk wil be used to select WM*/

		if (ranges->reader_wm_sets[num_valid_sets].wm_type == WM_TYPE_PSTATE_CHG) {
			if (i == 0)
				ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = 0;
			else {
				/* add 1 to make it non-overlapping with next lvl */
				ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = bw_params->clk_table.entries[i - 1].fclk_mhz + 1;
			}
			ranges->reader_wm_sets[num_valid_sets].max_fill_clk_mhz = bw_params->clk_table.entries[i].fclk_mhz;

		} else {
			/* unconstrained for memory retraining */
			ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
			ranges->reader_wm_sets[num_valid_sets].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;

			/* Modify previous watermark range to cover up to max */
			ranges->reader_wm_sets[num_valid_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
		}
		num_valid_sets++;
	}

	ASSERT(num_valid_sets != 0); /* Must have at least one set of valid watermarks */
	ranges->num_reader_wm_sets = num_valid_sets;

	/* modify the min and max to make sure we cover the whole range*/
	ranges->reader_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
	ranges->reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
	ranges->reader_wm_sets[ranges->num_reader_wm_sets - 1].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
	ranges->reader_wm_sets[ranges->num_reader_wm_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;

	/* This is for writeback only, does not matter currently as no writeback support*/
	ranges->num_writer_wm_sets = 1;
	ranges->writer_wm_sets[0].wm_inst = WM_A;
	ranges->writer_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
	ranges->writer_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
	ranges->writer_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
	ranges->writer_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;

}

static void rn_notify_wm_ranges(struct clk_mgr *clk_mgr_base)
{
	struct dc_debug_options *debug = &clk_mgr_base->ctx->dc->debug;
	struct pp_smu_wm_range_sets ranges = {0};
	struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
	struct pp_smu_funcs *pp_smu = clk_mgr->pp_smu;

	if (!debug->disable_pplib_wm_range) {
		build_watermark_ranges(clk_mgr_base->bw_params, &ranges);

		/* Notify PP Lib/SMU which Watermarks to use for which clock ranges */
		if (pp_smu && pp_smu->rn_funcs.set_wm_ranges)
			pp_smu->rn_funcs.set_wm_ranges(&pp_smu->rn_funcs.pp_smu, &ranges);
	}

}

static struct clk_mgr_funcs dcn21_funcs = {
	.get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
	.update_clocks = rn_update_clocks,
	.init_clocks = rn_init_clocks,
	.enable_pme_wa = rn_enable_pme_wa,
	/* .dump_clk_registers = rn_dump_clk_registers */
	/* .dump_clk_registers = rn_dump_clk_registers, */
	.notify_wm_ranges = rn_notify_wm_ranges
};

struct clk_bw_params rn_bw_params = {
@@ -472,63 +547,6 @@ struct clk_bw_params rn_bw_params = {
	}
};

static void rn_build_watermark_ranges(struct clk_bw_params *bw_params, struct pp_smu_wm_range_sets *ranges)
{
	int i, num_valid_sets;

	num_valid_sets = 0;

	for (i = 0; i < WM_SET_COUNT; i++) {
		/* skip empty entries, the smu array has no holes*/
		if (!bw_params->wm_table.entries[i].valid)
			continue;

		ranges->reader_wm_sets[num_valid_sets].wm_inst = bw_params->wm_table.entries[i].wm_inst;
		ranges->reader_wm_sets[num_valid_sets].wm_type = bw_params->wm_table.entries[i].wm_type;;
		/* We will not select WM based on dcfclk, so leave it as unconstrained */
		ranges->reader_wm_sets[num_valid_sets].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
		ranges->reader_wm_sets[num_valid_sets].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
		/* fclk wil be used to select WM*/

		if (ranges->reader_wm_sets[num_valid_sets].wm_type == WM_TYPE_PSTATE_CHG) {
			if (i == 0)
				ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = 0;
			else {
				/* add 1 to make it non-overlapping with next lvl */
				ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = bw_params->clk_table.entries[i - 1].fclk_mhz + 1;
			}
			ranges->reader_wm_sets[num_valid_sets].max_fill_clk_mhz = bw_params->clk_table.entries[i].fclk_mhz;

		} else {
			/* unconstrained for memory retraining */
			ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
			ranges->reader_wm_sets[num_valid_sets].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;

			/* Modify previous watermark range to cover up to max */
			ranges->reader_wm_sets[num_valid_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
		}
		num_valid_sets++;
	}

	ASSERT(num_valid_sets != 0); /* Must have at least one set of valid watermarks */
	ranges->num_reader_wm_sets = num_valid_sets;

	/* modify the min and max to make sure we cover the whole range*/
	ranges->reader_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
	ranges->reader_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
	ranges->reader_wm_sets[ranges->num_reader_wm_sets - 1].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
	ranges->reader_wm_sets[ranges->num_reader_wm_sets - 1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;

	/* This is for writeback only, does not matter currently as no writeback support*/
	ranges->num_writer_wm_sets = 1;
	ranges->writer_wm_sets[0].wm_inst = WM_A;
	ranges->writer_wm_sets[0].min_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
	ranges->writer_wm_sets[0].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
	ranges->writer_wm_sets[0].min_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
	ranges->writer_wm_sets[0].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;

}

static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage)
{
	int i;
@@ -661,21 +679,6 @@ void rn_clk_mgr_construct(
		rn_clk_mgr_helper_populate_bw_params(clk_mgr->base.bw_params, &clock_table, &ctx->asic_id);
	}

	/*
	 * Notify SMU which set of WM should be selected for different ranges of fclk
	 * On Renoir there is a maximumum of 4 DF pstates supported, could be less
	 * depending on DDR speed and fused maximum fclk.
	 */
	if (!debug->disable_pplib_wm_range) {
		struct pp_smu_wm_range_sets ranges = {0};

		rn_build_watermark_ranges(clk_mgr->base.bw_params, &ranges);

		/* Notify PP Lib/SMU which Watermarks to use for which clock ranges */
		if (pp_smu && pp_smu->rn_funcs.set_wm_ranges)
			pp_smu->rn_funcs.set_wm_ranges(&pp_smu->rn_funcs.pp_smu, &ranges);
	}

	if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment) && clk_mgr->smu_ver >= 0x00371500) {
		/* enable powerfeatures when displaycount goes to 0 */
		rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(clk_mgr, !debug->disable_48mhz_pwrdwn);
+4 −0
Original line number Diff line number Diff line
@@ -1304,6 +1304,10 @@ static void dcn10_init_hw(struct dc *dc)
	}

	dc->hwss.enable_power_gating_plane(dc->hwseq, true);

	if (dc->clk_mgr->funcs->notify_wm_ranges)
		dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);

}

static void dcn10_reset_hw_ctx_wrap(
+1 −0
Original line number Diff line number Diff line
@@ -183,6 +183,7 @@ struct clk_mgr_funcs {

	bool (*are_clock_states_equal) (struct dc_clocks *a,
			struct dc_clocks *b);
	void (*notify_wm_ranges)(struct clk_mgr *clk_mgr);
};

struct clk_mgr {