From 04885368cbc85736d61b79c7624aeed238fde93b Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Mon, 14 Jan 2019 15:24:59 +0800 Subject: [PATCH] drm/amd/powerplay: add interface to request display clock voltage This patch adds interface to request display clock voltage, display will use it to request current display clock voltage. Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- .../amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | 17 ++++--- .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 5 +++ drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 44 +++++++++++++++++++ 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c index 15a94e55f30a..389118e3f527 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c @@ -476,6 +476,10 @@ bool dm_pp_apply_clock_for_voltage_request( ret = adev->powerplay.pp_funcs->display_clock_voltage_request( adev->powerplay.pp_handle, &pp_clock_request); + else if (adev->smu.funcs && + adev->smu.funcs->display_clock_voltage_request) + ret = smu_display_clock_voltage_request(&adev->smu, + &pp_clock_request); if (ret) return false; return true; @@ -512,16 +516,19 @@ void pp_rv_set_display_requirement(struct pp_smu *pp, const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; struct pp_display_clock_request clock = {0}; - if (!pp_funcs || !pp_funcs->display_clock_voltage_request) - return; - clock.clock_type = amd_pp_dcf_clock; clock.clock_freq_in_khz = req->hard_min_dcefclk_mhz * 1000; - pp_funcs->display_clock_voltage_request(pp_handle, &clock); + if (pp_funcs && pp_funcs->display_clock_voltage_request) + pp_funcs->display_clock_voltage_request(pp_handle, &clock); + else if (adev->smu.funcs && adev->smu.funcs->display_clock_voltage_request) + smu_display_clock_voltage_request(&adev->smu, &clock); clock.clock_type = amd_pp_f_clock; clock.clock_freq_in_khz = req->hard_min_fclk_mhz * 1000; - pp_funcs->display_clock_voltage_request(pp_handle, &clock); + if (pp_funcs && pp_funcs->display_clock_voltage_request) + pp_funcs->display_clock_voltage_request(pp_handle, &clock); + else if (adev->smu.funcs && adev->smu.funcs->display_clock_voltage_request) + smu_display_clock_voltage_request(&adev->smu, &clock); } void pp_rv_set_wm_ranges(struct pp_smu *pp, diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index 9b0080427de6..9d16db16f2b5 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -284,6 +284,9 @@ struct smu_funcs struct amd_pp_clocks *clocks); int (*get_max_high_clocks)(struct smu_context *smu, struct amd_pp_simple_clock_info *clocks); + int (*display_clock_voltage_request)(struct smu_context *smu, struct + pp_display_clock_request + *clock_req); }; #define smu_init_microcode(smu) \ @@ -393,6 +396,8 @@ struct smu_funcs ((smu)->ppt_funcs->get_clock_by_type_with_latency ? (smu)->ppt_funcs->get_clock_by_type_with_latency((smu), (type), (clocks)) : 0) #define smu_get_clock_by_type_with_voltage(smu, type, clocks) \ ((smu)->ppt_funcs->get_clock_by_type_with_voltage ? (smu)->ppt_funcs->get_clock_by_type_with_voltage((smu), (type), (clocks)) : 0) +#define smu_display_clock_voltage_request(smu, clock_req) \ + ((smu)->funcs->display_clock_voltage_request ? (smu)->funcs->display_clock_voltage_request((smu), (clock_req)) : 0) extern int smu_get_atom_data_table(struct smu_context *smu, uint32_t table, diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index 5987c89d4155..04d949e220d2 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -1124,6 +1124,49 @@ static int smu_v11_0_read_sensor(struct smu_context *smu, return ret; } +static int +smu_v11_0_display_clock_voltage_request(struct smu_context *smu, + struct pp_display_clock_request + *clock_req) +{ + enum amd_pp_clock_type clk_type = clock_req->clock_type; + int ret = 0; + PPCLK_e clk_select = 0; + uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; + + mutex_lock(&smu->mutex); + if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) { + switch (clk_type) { + case amd_pp_dcef_clock: + clk_select = PPCLK_DCEFCLK; + break; + case amd_pp_disp_clock: + clk_select = PPCLK_DISPCLK; + break; + case amd_pp_pixel_clock: + clk_select = PPCLK_PIXCLK; + break; + case amd_pp_phy_clock: + clk_select = PPCLK_PHYCLK; + break; + default: + pr_info("[%s] Invalid Clock Type!", __func__); + ret = -EINVAL; + break; + } + + if (ret) + goto failed; + + ret = smu_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq, + (clk_select << 16) | clk_freq); + } + +failed: + mutex_unlock(&smu->mutex); + return ret; +} + static const struct smu_funcs smu_v11_0_funcs = { .init_microcode = smu_v11_0_init_microcode, .load_microcode = smu_v11_0_load_microcode, @@ -1158,6 +1201,7 @@ static const struct smu_funcs smu_v11_0_funcs = { .start_thermal_control = smu_v11_0_start_thermal_control, .read_sensor = smu_v11_0_read_sensor, .set_deep_sleep_dcefclk = smu_v11_0_set_deep_sleep_dcefclk, + .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, }; void smu_v11_0_set_smu_funcs(struct smu_context *smu) -- 2.30.2