aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0613-drm-amd-dal-Integrate-amd_powerplay_get_clock_by_typ.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0613-drm-amd-dal-Integrate-amd_powerplay_get_clock_by_typ.patch')
-rw-r--r--common/recipes-kernel/linux/files/0613-drm-amd-dal-Integrate-amd_powerplay_get_clock_by_typ.patch241
1 files changed, 241 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0613-drm-amd-dal-Integrate-amd_powerplay_get_clock_by_typ.patch b/common/recipes-kernel/linux/files/0613-drm-amd-dal-Integrate-amd_powerplay_get_clock_by_typ.patch
new file mode 100644
index 00000000..a2e8e7d3
--- /dev/null
+++ b/common/recipes-kernel/linux/files/0613-drm-amd-dal-Integrate-amd_powerplay_get_clock_by_typ.patch
@@ -0,0 +1,241 @@
+From 16c580abc2cbfc2a6dedecd88773bce4c0611a12 Mon Sep 17 00:00:00 2001
+From: "Signed-off-by: David Rokhvarg" <David.Rokhvarg@amd.com>
+Date: Thu, 3 Mar 2016 17:32:18 -0500
+Subject: [PATCH 0613/1110] drm/amd/dal: Integrate
+ amd_powerplay_get_clock_by_type() into DM.
+
+This replaces hardcoded values by PPLib values.
+
+Signed-off-by: David Rokhvarg <David.Rokhvarg@amd.com>
+Signed-off-by: Harry Wentland <harry.wentland@amd.com>
+Acked-by: Harry Wentland<harry.wentland@amd.com>
+---
+ .../drm/amd/dal/amdgpu_dm/amdgpu_dal_services.c | 155 +++++++++++++++++----
+ drivers/gpu/drm/amd/dal/dc/dc_services.h | 8 +-
+ 2 files changed, 133 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dal_services.c b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dal_services.c
+index 94c8a38..12b9475 100644
+--- a/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dal_services.c
++++ b/drivers/gpu/drm/amd/dal/amdgpu_dm/amdgpu_dal_services.c
+@@ -258,34 +258,24 @@ bool dc_service_get_system_clocks_range(
+ return true;
+ }
+
+-
+-bool dc_service_pp_get_clock_levels_by_type(
+- const struct dc_context *ctx,
++static void get_default_clock_levels(
+ enum dc_pp_clock_type clk_type,
+ struct dc_pp_clock_levels *clks)
+ {
+-/*
+- #ifdef CONFIG_DRM_AMD_POWERPLAY
+- if(amd_powerplay_get_clocks_by_type(adev->powerplay.pp_handle,
+- (int)clk_type, (void *)clks) == fail
+- PPlib return clocks in tens of kHz
+- divide by 10 & push to the clks which kHz
+-#endif
+-*/
+- uint32_t disp_clks_in_khz[8] = {
+- 300000, 411430, 480000, 533340, 626090, 626090, 626090, 626090 };
+- uint32_t sclks_in_khz[8] = {
+- 200000, 266670, 342860, 411430, 450000, 514290, 576000, 626090 };
+- uint32_t mclks_in_khz[8] = { 333000, 800000 };
++ uint32_t disp_clks_in_khz[6] = {
++ 300000, 400000, 496560, 626090, 685720, 757900 };
++ uint32_t sclks_in_khz[6] = {
++ 300000, 360000, 423530, 514290, 626090, 720000 };
++ uint32_t mclks_in_khz[2] = { 333000, 800000 };
+
+ switch (clk_type) {
+ case DC_PP_CLOCK_TYPE_DISPLAY_CLK:
+- clks->num_levels = 8;
++ clks->num_levels = 6;
+ dc_service_memmove(clks->clocks_in_khz, disp_clks_in_khz,
+ sizeof(disp_clks_in_khz));
+ break;
+ case DC_PP_CLOCK_TYPE_ENGINE_CLK:
+- clks->num_levels = 8;
++ clks->num_levels = 6;
+ dc_service_memmove(clks->clocks_in_khz, sclks_in_khz,
+ sizeof(sclks_in_khz));
+ break;
+@@ -295,26 +285,135 @@ bool dc_service_pp_get_clock_levels_by_type(
+ sizeof(mclks_in_khz));
+ break;
+ default:
+- return false;
++ clks->num_levels = 0;
++ break;
+ }
++}
+
+ #ifdef CONFIG_DRM_AMD_POWERPLAY
+- if (clk_type == DC_PP_CLOCK_TYPE_ENGINE_CLK ||
+- clk_type == DC_PP_CLOCK_TYPE_DISPLAY_CLK) {
++static enum amd_pp_clock_type dc_to_pp_clock_type(
++ enum dc_pp_clock_type dc_pp_clk_type)
++{
++ enum amd_pp_clock_type amd_pp_clk_type = 0;
++
++ switch (dc_pp_clk_type) {
++ case DC_PP_CLOCK_TYPE_DISPLAY_CLK:
++ amd_pp_clk_type = amd_pp_disp_clock;
++ break;
++ case DC_PP_CLOCK_TYPE_ENGINE_CLK:
++ amd_pp_clk_type = amd_pp_sys_clock;
++ break;
++ case DC_PP_CLOCK_TYPE_MEMORY_CLK:
++ amd_pp_clk_type = amd_pp_mem_clock;
++ break;
++ default:
++ DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n",
++ dc_pp_clk_type);
++ break;
++ }
+
+- struct amdgpu_device *adev = ctx->driver_context;
+- struct amd_pp_dal_clock_info info = {0};
++ return amd_pp_clk_type;
++}
++
++static void pp_to_dc_clock_levels(
++ const struct amd_pp_clocks *pp_clks,
++ struct dc_pp_clock_levels *dc_clks,
++ enum dc_pp_clock_type dc_clk_type)
++{
++ uint32_t i;
+
+- if (0 == amd_powerplay_get_display_power_level(
+- adev->powerplay.pp_handle, &info) &&
+- info.level < clks->num_levels) {
+- /*if the max possible power level less then use smaller*/
+- clks->num_levels = info.level;
++ if (pp_clks->count > DC_PP_MAX_CLOCK_LEVELS) {
++ DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
++ DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
++ pp_clks->count,
++ DC_PP_MAX_CLOCK_LEVELS);
++
++ dc_clks->num_levels = DC_PP_MAX_CLOCK_LEVELS;
++ } else
++ dc_clks->num_levels = pp_clks->count;
++
++ DRM_INFO("DM_PPLIB: values for %s clock\n",
++ DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
++
++ for (i = 0; i < dc_clks->num_levels; i++) {
++ DRM_INFO("DM_PPLIB:\t %d\n", pp_clks->clock[i]);
++ /* translate 10kHz to kHz */
++ dc_clks->clocks_in_khz[i] = pp_clks->clock[i] * 10;
++ }
++}
++#endif
++
++bool dc_service_pp_get_clock_levels_by_type(
++ const struct dc_context *ctx,
++ enum dc_pp_clock_type clk_type,
++ struct dc_pp_clock_levels *dc_clks)
++{
++#ifdef CONFIG_DRM_AMD_POWERPLAY
++ struct amdgpu_device *adev = ctx->driver_context;
++ void *pp_handle = adev->powerplay.pp_handle;
++ struct amd_pp_clocks pp_clks = { 0 };
++ struct amd_pp_simple_clock_info validation_clks = { 0 };
++ uint32_t i;
++
++ if (amd_powerplay_get_clock_by_type(pp_handle,
++ dc_to_pp_clock_type(clk_type), &pp_clks)) {
++ /* Error in pplib. Provide default values. */
++ get_default_clock_levels(clk_type, dc_clks);
++ return true;
++ }
++
++ pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type);
++
++ if (amd_powerplay_get_display_mode_validation_clocks(pp_handle,
++ &validation_clks)) {
++ /* Error in pplib. Provide default values. */
++ DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
++ validation_clks.engine_max_clock = 72000;
++ validation_clks.memory_max_clock = 80000;
++ validation_clks.level = 0;
++ }
++
++ DRM_INFO("DM_PPLIB: Validation clocks:\n");
++ DRM_INFO("DM_PPLIB: engine_max_clock: %d\n",
++ validation_clks.engine_max_clock);
++ DRM_INFO("DM_PPLIB: memory_max_clock: %d\n",
++ validation_clks.memory_max_clock);
++ DRM_INFO("DM_PPLIB: level : %d\n",
++ validation_clks.level);
++
++ /* Translate 10 kHz to kHz. */
++ validation_clks.engine_max_clock *= 10;
++ validation_clks.memory_max_clock *= 10;
++
++ /* Determine the highest non-boosted level from the Validation Clocks */
++ if (clk_type == DC_PP_CLOCK_TYPE_ENGINE_CLK) {
++ for (i = 0; i < dc_clks->num_levels; i++) {
++ if (dc_clks->clocks_in_khz[i] > validation_clks.engine_max_clock) {
++ /* This clock is higher the validation clock.
++ * Than means the previous one is the highest
++ * non-boosted one. */
++ DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n",
++ dc_clks->num_levels, i + 1);
++ dc_clks->num_levels = i;
++ break;
++ }
++ }
++ } else if (clk_type == DC_PP_CLOCK_TYPE_MEMORY_CLK) {
++ for (i = 0; i < dc_clks->num_levels; i++) {
++ if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) {
++ DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n",
++ dc_clks->num_levels, i + 1);
++ dc_clks->num_levels = i;
++ break;
++ }
+ }
+ }
++#else
++ get_default_clock_levels(clk_type, dc_clks);
+ #endif
+ return true;
+ }
++
+ /**** end of power component interfaces ****/
+
+
+diff --git a/drivers/gpu/drm/amd/dal/dc/dc_services.h b/drivers/gpu/drm/amd/dal/dc/dc_services.h
+index edb558d..907b415 100644
+--- a/drivers/gpu/drm/amd/dal/dc/dc_services.h
++++ b/drivers/gpu/drm/amd/dal/dc/dc_services.h
+@@ -105,7 +105,6 @@ struct dc_pp_display_configuration {
+ bool cpu_pstate_disable;
+ uint32_t cpu_pstate_separation_time;
+
+- /* 10khz steps */
+ uint32_t min_memory_clock_khz;
+ uint32_t min_engine_clock_khz;
+ uint32_t min_engine_clock_deep_sleep_khz;
+@@ -167,10 +166,15 @@ bool dc_service_get_system_clocks_range(
+
+ enum dc_pp_clock_type {
+ DC_PP_CLOCK_TYPE_DISPLAY_CLK = 1,
+- DC_PP_CLOCK_TYPE_ENGINE_CLK,
++ DC_PP_CLOCK_TYPE_ENGINE_CLK, /* System clock */
+ DC_PP_CLOCK_TYPE_MEMORY_CLK
+ };
+
++#define DC_DECODE_PP_CLOCK_TYPE(clk_type) \
++ (clk_type) == DC_PP_CLOCK_TYPE_DISPLAY_CLK ? "Display" : \
++ (clk_type) == DC_PP_CLOCK_TYPE_ENGINE_CLK ? "Engine" : \
++ (clk_type) == DC_PP_CLOCK_TYPE_MEMORY_CLK ? "Memory" : "Invalid"
++
+ #define DC_PP_MAX_CLOCK_LEVELS 8
+
+ struct dc_pp_clock_levels {
+--
+2.7.4
+