[PATCH 18/77] drm/amd/display: refactor pplib/smu communication

Harry Wentland harry.wentland at amd.com
Thu Aug 31 18:08:13 UTC 2017


From: Tony Cheng <tony.cheng at amd.com>

new per SoC interface instead legacy interface with lots of un-used
field that only cause confusion

model pp_smu like one of our HW objects with func_ptr interface
to call into it.  struct pp_smu as handle to call pp/smu

Signed-off-by: Tony Cheng <tony.cheng at amd.com>
Reviewed-by: Jun Lei <Jun.Lei at amd.com>
Acked-by: Harry Wentland <Harry.Wentland at amd.com>
---
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_services.c |  13 +-
 drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c   | 100 ++++++++--------
 .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c  |  19 ++-
 drivers/gpu/drm/amd/display/dc/dm_pp_smu.h         | 131 +++++++++++++++++++++
 drivers/gpu/drm/amd/display/dc/dm_services.h       |   5 +-
 drivers/gpu/drm/amd/display/dc/dm_services_types.h |   2 +
 drivers/gpu/drm/amd/display/dc/inc/core_types.h    |   2 +
 drivers/gpu/drm/amd/display/dc/inc/resource.h      |   1 +
 8 files changed, 213 insertions(+), 60 deletions(-)
 create mode 100644 drivers/gpu/drm/amd/display/dc/dm_pp_smu.h

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c
index 3348e90a0a37..aefd9ebc7bce 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c
@@ -401,14 +401,6 @@ bool dm_pp_notify_wm_clock_changes(
 	return false;
 }
 
-bool dm_pp_notify_wm_clock_changes_soc15(
-	const struct dc_context *ctx,
-	struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges)
-{
-	/* TODO: to be implemented */
-	return false;
-}
-
 bool dm_pp_apply_power_level_change_request(
 	const struct dc_context *ctx,
 	struct dm_pp_power_level_change_request *level_change_req)
@@ -433,4 +425,9 @@ bool dm_pp_get_static_clocks(
 	return false;
 }
 
+void dm_pp_get_funcs_rv(
+		struct dc_context *ctx,
+		struct pp_smu_funcs_rv *funcs)
+{}
+
 /**** end of power component interfaces ****/
diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
index f0dfd3c3c12c..afd403ceb2a7 100644
--- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
@@ -1311,12 +1311,16 @@ void dcn_bw_update_from_pplib(struct dc *dc)
 
 void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc)
 {
-	struct dm_pp_wm_sets_with_clock_ranges_soc15 clk_ranges = {0};
+	struct pp_smu_funcs_rv *pp = dc->res_pool->pp_smu;
+	struct pp_smu_wm_range_sets ranges = {0};
 	int max_fclk_khz, nom_fclk_khz, min_fclk_khz, max_dcfclk_khz,
 		nom_dcfclk_khz, mid_fclk_khz, min_dcfclk_khz, socclk_khz;
 	const int overdrive = 5000000; /* 5 GHz to cover Overdrive */
 	unsigned factor = (ddr4_dram_factor_single_Channel * dc->dcn_soc->number_of_channels);
 
+	if (!pp->set_wm_ranges)
+		return;
+
 	kernel_fpu_begin();
 	max_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 * 1000000 / factor;
 	nom_fclk_khz = dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 * 1000000 / factor;
@@ -1336,55 +1340,55 @@ void dcn_bw_notify_pplib_of_wm_ranges(struct dc *dc)
 	/* SOCCLK does not affect anytihng but writeback for DCN so for now we dont
 	 * care what the value is, hence min to overdrive level
 	 */
-	clk_ranges.num_wm_dmif_sets = 4;
-	clk_ranges.num_wm_mcif_sets = 4;
-	clk_ranges.wm_dmif_clocks_ranges[0].wm_set_id = WM_SET_A;
-	clk_ranges.wm_dmif_clocks_ranges[0].wm_min_dcfclk_clk_in_khz = min_dcfclk_khz;
-	clk_ranges.wm_dmif_clocks_ranges[0].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz;
-	clk_ranges.wm_dmif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz;
-	clk_ranges.wm_dmif_clocks_ranges[0].wm_max_mem_clk_in_khz = min_fclk_khz;
-	clk_ranges.wm_mcif_clocks_ranges[0].wm_set_id = WM_SET_A;
-	clk_ranges.wm_mcif_clocks_ranges[0].wm_min_socclk_clk_in_khz = socclk_khz;
-	clk_ranges.wm_mcif_clocks_ranges[0].wm_max_socclk_clk_in_khz = overdrive;
-	clk_ranges.wm_mcif_clocks_ranges[0].wm_min_memg_clk_in_khz = min_fclk_khz;
-	clk_ranges.wm_mcif_clocks_ranges[0].wm_max_mem_clk_in_khz = min_fclk_khz;
-
-	clk_ranges.wm_dmif_clocks_ranges[1].wm_set_id = WM_SET_B;
-	clk_ranges.wm_dmif_clocks_ranges[1].wm_min_dcfclk_clk_in_khz = min_fclk_khz;
-	clk_ranges.wm_dmif_clocks_ranges[1].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz;
-	clk_ranges.wm_dmif_clocks_ranges[1].wm_min_memg_clk_in_khz = mid_fclk_khz;
-	clk_ranges.wm_dmif_clocks_ranges[1].wm_max_mem_clk_in_khz = mid_fclk_khz;
-	clk_ranges.wm_mcif_clocks_ranges[1].wm_set_id = WM_SET_B;
-	clk_ranges.wm_mcif_clocks_ranges[1].wm_min_socclk_clk_in_khz = socclk_khz;
-	clk_ranges.wm_mcif_clocks_ranges[1].wm_max_socclk_clk_in_khz = overdrive;
-	clk_ranges.wm_mcif_clocks_ranges[1].wm_min_memg_clk_in_khz = mid_fclk_khz;
-	clk_ranges.wm_mcif_clocks_ranges[1].wm_max_mem_clk_in_khz = mid_fclk_khz;
-
-
-	clk_ranges.wm_dmif_clocks_ranges[2].wm_set_id = WM_SET_C;
-	clk_ranges.wm_dmif_clocks_ranges[2].wm_min_dcfclk_clk_in_khz = min_fclk_khz;
-	clk_ranges.wm_dmif_clocks_ranges[2].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz;
-	clk_ranges.wm_dmif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz;
-	clk_ranges.wm_dmif_clocks_ranges[2].wm_max_mem_clk_in_khz = nom_fclk_khz;
-	clk_ranges.wm_mcif_clocks_ranges[2].wm_set_id = WM_SET_C;
-	clk_ranges.wm_mcif_clocks_ranges[2].wm_min_socclk_clk_in_khz = socclk_khz;
-	clk_ranges.wm_mcif_clocks_ranges[2].wm_max_socclk_clk_in_khz = overdrive;
-	clk_ranges.wm_mcif_clocks_ranges[2].wm_min_memg_clk_in_khz = nom_fclk_khz;
-	clk_ranges.wm_mcif_clocks_ranges[2].wm_max_mem_clk_in_khz = nom_fclk_khz;
-
-	clk_ranges.wm_dmif_clocks_ranges[3].wm_set_id = WM_SET_D;
-	clk_ranges.wm_dmif_clocks_ranges[3].wm_min_dcfclk_clk_in_khz = min_fclk_khz;
-	clk_ranges.wm_dmif_clocks_ranges[3].wm_max_dcfclk_clk_in_khz = max_dcfclk_khz;
-	clk_ranges.wm_dmif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz;
-	clk_ranges.wm_dmif_clocks_ranges[3].wm_max_mem_clk_in_khz = max_fclk_khz;
-	clk_ranges.wm_mcif_clocks_ranges[3].wm_set_id = WM_SET_D;
-	clk_ranges.wm_mcif_clocks_ranges[3].wm_min_socclk_clk_in_khz = socclk_khz;
-	clk_ranges.wm_mcif_clocks_ranges[3].wm_max_socclk_clk_in_khz = overdrive;
-	clk_ranges.wm_mcif_clocks_ranges[3].wm_min_memg_clk_in_khz = max_fclk_khz;
-	clk_ranges.wm_mcif_clocks_ranges[3].wm_max_mem_clk_in_khz = max_fclk_khz;
+	ranges.num_reader_wm_sets = WM_COUNT;
+	ranges.num_writer_wm_sets = WM_COUNT;
+	ranges.reader_wm_sets[0].wm_inst = WM_A;
+	ranges.reader_wm_sets[0].min_drain_clk_khz = min_dcfclk_khz;
+	ranges.reader_wm_sets[0].max_drain_clk_khz = max_dcfclk_khz;
+	ranges.reader_wm_sets[0].min_fill_clk_khz = min_fclk_khz;
+	ranges.reader_wm_sets[0].max_fill_clk_khz = min_fclk_khz;
+	ranges.writer_wm_sets[0].wm_inst = WM_A;
+	ranges.writer_wm_sets[0].min_fill_clk_khz = socclk_khz;
+	ranges.writer_wm_sets[0].max_fill_clk_khz = overdrive;
+	ranges.writer_wm_sets[0].min_drain_clk_khz = min_fclk_khz;
+	ranges.writer_wm_sets[0].max_drain_clk_khz = min_fclk_khz;
+
+	ranges.reader_wm_sets[1].wm_inst = WM_B;
+	ranges.reader_wm_sets[1].min_drain_clk_khz = min_fclk_khz;
+	ranges.reader_wm_sets[1].max_drain_clk_khz = max_dcfclk_khz;
+	ranges.reader_wm_sets[1].min_fill_clk_khz = mid_fclk_khz;
+	ranges.reader_wm_sets[1].max_fill_clk_khz = mid_fclk_khz;
+	ranges.writer_wm_sets[1].wm_inst = WM_B;
+	ranges.writer_wm_sets[1].min_fill_clk_khz = socclk_khz;
+	ranges.writer_wm_sets[1].max_fill_clk_khz = overdrive;
+	ranges.writer_wm_sets[1].min_drain_clk_khz = mid_fclk_khz;
+	ranges.writer_wm_sets[1].max_drain_clk_khz = mid_fclk_khz;
+
+
+	ranges.reader_wm_sets[2].wm_inst = WM_C;
+	ranges.reader_wm_sets[2].min_drain_clk_khz = min_fclk_khz;
+	ranges.reader_wm_sets[2].max_drain_clk_khz = max_dcfclk_khz;
+	ranges.reader_wm_sets[2].min_fill_clk_khz = nom_fclk_khz;
+	ranges.reader_wm_sets[2].max_fill_clk_khz = nom_fclk_khz;
+	ranges.writer_wm_sets[2].wm_inst = WM_C;
+	ranges.writer_wm_sets[2].min_fill_clk_khz = socclk_khz;
+	ranges.writer_wm_sets[2].max_fill_clk_khz = overdrive;
+	ranges.writer_wm_sets[2].min_drain_clk_khz = nom_fclk_khz;
+	ranges.writer_wm_sets[2].max_drain_clk_khz = nom_fclk_khz;
+
+	ranges.reader_wm_sets[3].wm_inst = WM_D;
+	ranges.reader_wm_sets[3].min_drain_clk_khz = min_fclk_khz;
+	ranges.reader_wm_sets[3].max_drain_clk_khz = max_dcfclk_khz;
+	ranges.reader_wm_sets[3].min_fill_clk_khz = max_fclk_khz;
+	ranges.reader_wm_sets[3].max_fill_clk_khz = max_fclk_khz;
+	ranges.writer_wm_sets[3].wm_inst = WM_D;
+	ranges.writer_wm_sets[3].min_fill_clk_khz = socclk_khz;
+	ranges.writer_wm_sets[3].max_fill_clk_khz = overdrive;
+	ranges.writer_wm_sets[3].min_drain_clk_khz = max_fclk_khz;
+	ranges.writer_wm_sets[3].max_drain_clk_khz = max_fclk_khz;
 
 	/* Notify PP Lib/SMU which Watermarks to use for which clock ranges */
-	dm_pp_notify_wm_clock_changes_soc15(dc->ctx, &clk_ranges);
+	pp->set_wm_ranges(&pp->pp_smu, &ranges);
 }
 
 void dcn_bw_sync_calcs_and_dml(struct dc *dc)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
index 2d9e88f08abb..954c234090db 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
@@ -678,6 +678,17 @@ void dcn10_clock_source_destroy(struct clock_source **clk_src)
 	*clk_src = NULL;
 }
 
+static struct pp_smu_funcs_rv *dcn10_pp_smu_create(struct dc_context *ctx)
+{
+	struct pp_smu_funcs_rv *pp_smu = dm_alloc(sizeof(*pp_smu));
+
+	if (!pp_smu)
+		return pp_smu;
+
+	dm_pp_get_funcs_rv(ctx, pp_smu);
+	return pp_smu;
+}
+
 static void destruct(struct dcn10_resource_pool *pool)
 {
 	unsigned int i;
@@ -751,6 +762,8 @@ static void destruct(struct dcn10_resource_pool *pool)
 
 	if (pool->base.display_clock != NULL)
 		dce_disp_clk_destroy(&pool->base.display_clock);
+
+	dm_free(pool->base.pp_smu);
 }
 
 static struct mem_input *dcn10_mem_input_create(
@@ -1347,11 +1360,15 @@ static bool construct(
 		}
 	}
 
+	pool->base.pp_smu = dcn10_pp_smu_create(ctx);
+
 	if (!dc->debug.disable_pplib_clock_request)
 		dcn_bw_update_from_pplib(dc);
 	dcn_bw_sync_calcs_and_dml(dc);
-	if (!dc->debug.disable_pplib_wm_range)
+	if (!dc->debug.disable_pplib_wm_range) {
+		dc->res_pool = &pool->base;
 		dcn_bw_notify_pplib_of_wm_ranges(dc);
+	}
 
 	{
 	#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
diff --git a/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h b/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h
new file mode 100644
index 000000000000..bbfa83252fc1
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/dm_pp_smu.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2017 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: AMD
+ *
+ */
+
+#ifndef DM_PP_SMU_IF__H
+#define DM_PP_SMU_IF__H
+
+/*
+ * interface to PPLIB/SMU to setup clocks and pstate requirements on SoC
+ */
+
+
+struct pp_smu {
+	struct dc_context *ctx;
+};
+
+enum wm_set_id {
+	WM_A,
+	WM_B,
+	WM_C,
+	WM_D,
+	WM_COUNT,
+};
+
+struct pp_smu_wm_set_range {
+	enum wm_set_id wm_inst;
+	uint32_t min_fill_clk_khz;
+	uint32_t max_fill_clk_khz;
+	uint32_t min_drain_clk_khz;
+	uint32_t max_drain_clk_khz;
+};
+
+struct pp_smu_wm_range_sets {
+	uint32_t num_reader_wm_sets;
+	struct pp_smu_wm_set_range reader_wm_sets[WM_COUNT];
+
+	uint32_t num_writer_wm_sets;
+	struct pp_smu_wm_set_range writer_wm_sets[WM_COUNT];
+};
+
+struct pp_smu_display_requirement_rv {
+	/* PPSMC_MSG_SetDisplayCount: count
+	 *  0 triggers S0i2 optimization
+	 */
+	unsigned int display_count;
+
+	/* PPSMC_MSG_SetHardMinFclkByFreq: khz
+	 *  FCLK will vary with DPM, but never below requested hard min
+	 */
+	unsigned int hard_min_fclk_khz;
+
+	/* PPSMC_MSG_SetHardMinDcefclkByFreq: khz
+	 *  fixed clock at requested freq, either from FCH bypass or DFS
+	 */
+	unsigned int hard_min_dcefclk_khz;
+
+	/* PPSMC_MSG_SetMinDeepSleepDcefclk: mhz
+	 *  when DF is in cstate, dcf clock is further divided down
+	 *  to just above given frequency
+	 */
+	unsigned int min_deep_sleep_dcefclk_mhz;
+};
+
+struct pp_smu_funcs_rv {
+	struct pp_smu pp_smu;
+
+	void (*set_display_requirement)(struct pp_smu *pp,
+			struct pp_smu_display_requirement_rv *req);
+
+	/* which SMU message?  are reader and writer WM separate SMU msg? */
+	void (*set_wm_ranges)(struct pp_smu *pp,
+			struct pp_smu_wm_range_sets *ranges);
+
+};
+
+#if 0
+struct pp_smu_funcs_rv {
+
+	/* PPSMC_MSG_SetDisplayCount
+	 *  0 triggers S0i2 optimization
+	 */
+	void (*set_display_count)(struct pp_smu *pp, int count);
+
+	/* PPSMC_MSG_SetHardMinFclkByFreq
+	 *  FCLK will vary with DPM, but never below requested hard min
+	 */
+	void (*set_hard_min_fclk_by_freq)(struct pp_smu *pp, int khz);
+
+	/* PPSMC_MSG_SetHardMinDcefclkByFreq
+	 *  fixed clock at requested freq, either from FCH bypass or DFS
+	 */
+	void (*set_hard_min_dcefclk_by_freq)(struct pp_smu *pp, int khz);
+
+	/* PPSMC_MSG_SetMinDeepSleepDcefclk
+	 *  when DF is in cstate, dcf clock is further divided down
+	 *  to just above given frequency
+	 */
+	void (*set_min_deep_sleep_dcefclk)(struct pp_smu *pp, int mhz);
+
+	/* todo: aesthetic
+	 * watermark range table
+	 */
+
+	/* todo: functional/feature
+	 * PPSMC_MSG_SetHardMinSocclkByFreq: required to support DWB
+	 */
+};
+#endif
+
+#endif /* DM_PP_SMU_IF__H */
diff --git a/drivers/gpu/drm/amd/display/dc/dm_services.h b/drivers/gpu/drm/amd/display/dc/dm_services.h
index e9bf4c417cc7..8ab0af6f4c6b 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_services.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_services.h
@@ -339,9 +339,8 @@ bool dm_pp_notify_wm_clock_changes(
 	const struct dc_context *ctx,
 	struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges);
 
-bool dm_pp_notify_wm_clock_changes_soc15(
-	const struct dc_context *ctx,
-	struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges);
+void dm_pp_get_funcs_rv(struct dc_context *ctx,
+		struct pp_smu_funcs_rv *funcs);
 
 /* DAL calls this function to notify PP about completion of Mode Set.
  * For PP it means that current DCE clocks are those which were returned
diff --git a/drivers/gpu/drm/amd/display/dc/dm_services_types.h b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
index 4c04ec587308..fa26cf488b3c 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_services_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_services_types.h
@@ -29,6 +29,8 @@
 #include "os_types.h"
 #include "dc_types.h"
 
+#include "dm_pp_smu.h"
+
 struct dm_pp_clock_range {
 	int min_khz;
 	int max_khz;
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 f8ade552c595..a3f0039088ab 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -48,6 +48,7 @@ void enable_surface_flip_reporting(struct dc_plane_state *plane_state,
 #include "clock_source.h"
 #include "audio.h"
 #include "hw_sequencer_types.h"
+#include "dm_pp_smu.h"
 
 
 /************ link *****************/
@@ -126,6 +127,7 @@ struct resource_pool {
 	struct stream_encoder *stream_enc[MAX_PIPES * 2];
 #ifdef CONFIG_DRM_AMD_DC_DCN1_0
 	struct mpc *mpc;
+	struct pp_smu_funcs_rv *pp_smu;
 #endif
 
 	struct dwbc *dwbc[MAX_DWB_PIPES];
diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h
index 13218a52e2fa..9085ec7ceac7 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
@@ -28,6 +28,7 @@
 #include "core_types.h"
 #include "core_status.h"
 #include "dal_asic_id.h"
+#include "dm_pp_smu.h"
 
 /* TODO unhardcode, 4 for CZ*/
 #define MEMORY_TYPE_MULTIPLIER 4
-- 
2.11.0



More information about the amd-gfx mailing list