From a5e65a3bdc11c64a135c4312bf79c6b7baf879c2 Mon Sep 17 00:00:00 2001 From: Vitaly Prosyak Date: Thu, 3 Dec 2015 13:48:04 -0500 Subject: [PATCH 0575/1110] drm/amd/dal: amd/dc Implement get memory and engine clocks from PPLib Added comments for clocks: PPLib uses tens of kHz, DM uses kHz, but DC does in fixed point MHz Signed-off-by: Harry Wentland Acked-by: Harry Wentland --- .../drm/amd/dal/amdgpu_dm/amdgpu_dal_services.c | 53 ++++++++++++++-------- drivers/gpu/drm/amd/dal/dc/core/dc.c | 45 +++++++++++++++--- drivers/gpu/drm/amd/dal/dc/dc_services.h | 2 +- 3 files changed, 73 insertions(+), 27 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 fd54703..2c02d18 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 @@ -234,43 +234,58 @@ bool dc_service_pp_get_clock_levels_by_type( enum dc_pp_clock_type clk_type, struct dc_pp_clock_levels *clks) { -#ifdef CONFIG_DRM_AMD_POWERPLAY -/* TODO: get clks from pplib. + +/* + #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 +*/ + struct amdgpu_device *adev = ctx->driver_context; - return (amd_powerplay_get_clocks_by_type(adev->powerplay.pp_handle, - (int)clk_type, (void *)clks) == 0); - */ - uint32_t disp_clks_in_hz[8] = { - 30000, 41143, 48000, 53334, 62609, 62609, 62609, 62609 }; - uint32_t sclks_in_hz[8] = { - 20000, 26667, 34286, 41143, 45000, 51429, 57600, 62609 }; - uint32_t mclks_in_hz[8] = { 33300, 80000, 0, 0, 0, 0, 0, 0 }; + 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 }; + + struct amd_pp_dal_clock_info info = {0}; switch (clk_type) { case DC_PP_CLOCK_TYPE_DISPLAY_CLK: clks->num_levels = 8; - dc_service_memmove(clks->clocks_in_hz, disp_clks_in_hz, 8); + 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; - dc_service_memmove(clks->clocks_in_hz, sclks_in_hz, 8); + dc_service_memmove(clks->clocks_in_khz, sclks_in_khz, + sizeof(sclks_in_khz)); break; case DC_PP_CLOCK_TYPE_MEMORY_CLK: clks->num_levels = 2; - dc_service_memmove(clks->clocks_in_hz, mclks_in_hz, 8); + dc_service_memmove(clks->clocks_in_khz, mclks_in_khz, + sizeof(mclks_in_khz)); break; default: return false; } - - return true; -#else - DRM_INFO("%s - not implemented\n", __func__); - return false; +#ifdef CONFIG_DRM_AMD_POWERPLAY + if (clk_type == DC_PP_CLOCK_TYPE_ENGINE_CLK || + clk_type == DC_PP_CLOCK_TYPE_DISPLAY_CLK) { + 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; + } + } #endif + return true; } - /**** end of power component interfaces ****/ diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc.c b/drivers/gpu/drm/amd/dal/dc/core/dc.c index 57277ed..599bf2f 100644 --- a/drivers/gpu/drm/amd/dal/dc/core/dc.c +++ b/drivers/gpu/drm/amd/dal/dc/core/dc.c @@ -226,9 +226,45 @@ static struct adapter_service *create_as( static void bw_calcs_data_update_from_pplib(struct dc *dc) { - struct dal_system_clock_range clk_range = { 0 }; + struct dc_pp_clock_levels clks = {0}; - dc_service_get_system_clocks_range(dc->ctx, &clk_range); + /*do system clock*/ + dc_service_pp_get_clock_levels_by_type( + dc->ctx, + DC_PP_CLOCK_TYPE_ENGINE_CLK, + &clks); + /* convert all the clock fro kHz to fix point mHz */ + dc->bw_vbios.high_sclk = frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1], 1000); + dc->bw_vbios.mid_sclk = frc_to_fixed( + clks.clocks_in_khz[clks.num_levels>>1], 1000); + dc->bw_vbios.low_sclk = frc_to_fixed( + clks.clocks_in_khz[0], 1000); + + /*do display clock*/ + dc_service_pp_get_clock_levels_by_type( + dc->ctx, + DC_PP_CLOCK_TYPE_DISPLAY_CLK, + &clks); + + dc->bw_vbios.high_voltage_max_dispclk = frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1], 1000); + dc->bw_vbios.mid_voltage_max_dispclk = frc_to_fixed( + clks.clocks_in_khz[clks.num_levels>>1], 1000); + dc->bw_vbios.low_voltage_max_dispclk = frc_to_fixed( + clks.clocks_in_khz[0], 1000); + + /*do memory clock*/ + dc_service_pp_get_clock_levels_by_type( + dc->ctx, + DC_PP_CLOCK_TYPE_MEMORY_CLK, + &clks); + + dc->bw_vbios.low_yclk = frc_to_fixed( + clks.clocks_in_khz[0], 1000); + dc->bw_vbios.high_yclk = frc_to_fixed( + clks.clocks_in_khz[clks.num_levels-1], 1000); + return; /* on CZ Gardenia from PPLib we get: * clk_range.max_mclk:80000 @@ -238,11 +274,6 @@ static void bw_calcs_data_update_from_pplib(struct dc *dc) /* The values for calcs are stored in units of MHz, so for example * 80000 will be stored as 800. */ - dc->bw_vbios.high_sclk = frc_to_fixed(clk_range.max_sclk, 100); - dc->bw_vbios.low_sclk = frc_to_fixed(clk_range.min_sclk, 100); - - dc->bw_vbios.high_yclk = frc_to_fixed(clk_range.max_mclk, 100); - dc->bw_vbios.low_yclk = frc_to_fixed(clk_range.min_mclk, 100); } static bool construct(struct dc *dc, const struct dal_init_data *init_params) diff --git a/drivers/gpu/drm/amd/dal/dc/dc_services.h b/drivers/gpu/drm/amd/dal/dc/dc_services.h index c2172ea..a584b6a 100644 --- a/drivers/gpu/drm/amd/dal/dc/dc_services.h +++ b/drivers/gpu/drm/amd/dal/dc/dc_services.h @@ -176,7 +176,7 @@ enum dc_pp_clock_type { struct dc_pp_clock_levels { uint32_t num_levels; - uint32_t clocks_in_hz[DC_PP_MAX_CLOCK_LEVELS]; + uint32_t clocks_in_khz[DC_PP_MAX_CLOCK_LEVELS]; /* TODO: add latency * do we need to know invalid (unsustainable boost) level for watermark -- 2.7.4