diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/0540-drm-amd-display-split-dccg-clock-manager-into-asic-f.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.19.8/0540-drm-amd-display-split-dccg-clock-manager-into-asic-f.patch | 967 |
1 files changed, 967 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/0540-drm-amd-display-split-dccg-clock-manager-into-asic-f.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/0540-drm-amd-display-split-dccg-clock-manager-into-asic-f.patch new file mode 100644 index 00000000..f001e0f8 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/0540-drm-amd-display-split-dccg-clock-manager-into-asic-f.patch @@ -0,0 +1,967 @@ +From f1ab2428459b22a026f8a6c1c83681fa8f725b98 Mon Sep 17 00:00:00 2001 +From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> +Date: Mon, 24 Sep 2018 15:28:00 -0400 +Subject: [PATCH 0540/2940] drm/amd/display: split dccg clock manager into asic + folders + +Currently dccg contains code related to every dcn revision in +a single file. + +This change splits out the dcn parts of code into correct folders + +Change-Id: I603351bdf753312e6b28e09320318d2afe7db852 +Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> +Reviewed-by: Charlene Liu <Charlene.Liu@amd.com> +Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com> +Signed-off-by: Kalyan Alle <kalyan.alle@amd.com> +--- + drivers/gpu/drm/amd/display/dc/dce/Makefile | 2 +- + .../dc/dce/{dce_clocks.c => dce_dccg.c} | 287 +----------------- + .../dc/dce/{dce_clocks.h => dce_dccg.h} | 48 ++- + .../amd/display/dc/dce100/dce100_resource.c | 2 +- + .../amd/display/dc/dce110/dce110_resource.c | 2 +- + .../amd/display/dc/dce112/dce112_resource.c | 2 +- + .../amd/display/dc/dce120/dce120_resource.c | 2 +- + .../drm/amd/display/dc/dce80/dce80_resource.c | 2 +- + drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- + .../gpu/drm/amd/display/dc/dcn10/dcn10_dccg.c | 278 +++++++++++++++++ + .../gpu/drm/amd/display/dc/dcn10/dcn10_dccg.h | 37 +++ + .../drm/amd/display/dc/dcn10/dcn10_resource.c | 2 +- + .../gpu/drm/amd/display/dc/inc/core_types.h | 2 +- + .../gpu/drm/amd/display/dc/inc/dcn_calcs.h | 2 +- + .../dc/inc/hw/{display_clock.h => dccg.h} | 6 +- + 15 files changed, 375 insertions(+), 301 deletions(-) + rename drivers/gpu/drm/amd/display/dc/dce/{dce_clocks.c => dce_dccg.c} (74%) + rename drivers/gpu/drm/amd/display/dc/dce/{dce_clocks.h => dce_dccg.h} (74%) + create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dccg.c + create mode 100644 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dccg.h + rename drivers/gpu/drm/amd/display/dc/inc/hw/{display_clock.h => dccg.h} (94%) + +diff --git a/drivers/gpu/drm/amd/display/dc/dce/Makefile b/drivers/gpu/drm/amd/display/dc/dce/Makefile +index 8f7f0e8b341f..f4ce7f502094 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/Makefile ++++ b/drivers/gpu/drm/amd/display/dc/dce/Makefile +@@ -28,7 +28,7 @@ + + DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \ + dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o \ +-dce_clocks.o dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o dce_aux.o \ ++dce_dccg.o dce_opp.o dce_dmcu.o dce_abm.o dce_ipp.o dce_aux.o \ + dce_i2c.o dce_i2c_hw.o dce_i2c_sw.o + + AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE)) +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_dccg.c +similarity index 74% +rename from drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +rename to drivers/gpu/drm/amd/display/dc/dce/dce_dccg.c +index 745f826df190..97c143b90edf 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dccg.c +@@ -23,10 +23,9 @@ + * + */ + ++#include "dce_dccg.h" ++ + #include "reg_helper.h" +-#include "bios_parser_interface.h" +-#include "dc.h" +-#include "dce_clocks.h" + #include "dmcu.h" + #include "core_types.h" + #include "dal_asic_id.h" +@@ -95,28 +94,6 @@ static const struct state_dependent_clocks dce120_max_clks_by_state[] = { + /*ClocksStatePerformance*/ + { .display_clk_khz = 1133000, .pixel_clk_khz = 600000 } }; + +-/* Starting DID for each range */ +-enum dentist_base_divider_id { +- DENTIST_BASE_DID_1 = 0x08, +- DENTIST_BASE_DID_2 = 0x40, +- DENTIST_BASE_DID_3 = 0x60, +- DENTIST_BASE_DID_4 = 0x7e, +- DENTIST_MAX_DID = 0x7f +-}; +- +-/* Starting point and step size for each divider range.*/ +-enum dentist_divider_range { +- DENTIST_DIVIDER_RANGE_1_START = 8, /* 2.00 */ +- DENTIST_DIVIDER_RANGE_1_STEP = 1, /* 0.25 */ +- DENTIST_DIVIDER_RANGE_2_START = 64, /* 16.00 */ +- DENTIST_DIVIDER_RANGE_2_STEP = 2, /* 0.50 */ +- DENTIST_DIVIDER_RANGE_3_START = 128, /* 32.00 */ +- DENTIST_DIVIDER_RANGE_3_STEP = 4, /* 1.00 */ +- DENTIST_DIVIDER_RANGE_4_START = 248, /* 62.00 */ +- DENTIST_DIVIDER_RANGE_4_STEP = 264, /* 66.00 */ +- DENTIST_DIVIDER_RANGE_SCALE_FACTOR = 4 +-}; +- + static int dentist_get_divider_from_did(int did) + { + if (did < DENTIST_BASE_DID_1) +@@ -130,12 +107,9 @@ static int dentist_get_divider_from_did(int did) + } else if (did < DENTIST_BASE_DID_3) { + return DENTIST_DIVIDER_RANGE_2_START + DENTIST_DIVIDER_RANGE_2_STEP + * (did - DENTIST_BASE_DID_2); +- } else if (did < DENTIST_BASE_DID_4) { ++ } else { + return DENTIST_DIVIDER_RANGE_3_START + DENTIST_DIVIDER_RANGE_3_STEP + * (did - DENTIST_BASE_DID_3); +- } else { +- return DENTIST_DIVIDER_RANGE_4_START + DENTIST_DIVIDER_RANGE_4_STEP +- * (did - DENTIST_BASE_DID_4); + } + } + +@@ -192,7 +166,7 @@ static int dce_get_dp_ref_freq_khz(struct dccg *dccg) + return dccg_adjust_dp_ref_freq_for_ss(dccg_dce, dp_ref_clk_khz); + } + +-static int dce12_get_dp_ref_freq_khz(struct dccg *dccg) ++int dce12_get_dp_ref_freq_khz(struct dccg *dccg) + { + struct dce_dccg *dccg_dce = TO_DCE_DCCG(dccg); + +@@ -305,9 +279,7 @@ static int dce_set_clock( + return actual_clock; + } + +-static int dce112_set_clock( +- struct dccg *dccg, +- int requested_clk_khz) ++int dce112_set_clock(struct dccg *dccg, int requested_clk_khz) + { + struct dce_dccg *dccg_dce = TO_DCE_DCCG(dccg); + struct bp_set_dce_clock_parameters dce_clk_params; +@@ -416,7 +388,7 @@ static void dce_clock_read_integrated_info(struct dce_dccg *dccg_dce) + dccg_dce->dfs_bypass_enabled = true; + } + +-static void dce_clock_read_ss_info(struct dce_dccg *dccg_dce) ++void dce_clock_read_ss_info(struct dce_dccg *dccg_dce) + { + struct dc_bios *bp = dccg_dce->base.ctx->dc_bios; + int ss_info_num = bp->funcs->get_ss_entry_number( +@@ -472,12 +444,7 @@ static void dce_clock_read_ss_info(struct dce_dccg *dccg_dce) + } + } + +-static inline bool should_set_clock(bool safe_to_lower, int calc_clk, int cur_clk) +-{ +- return ((safe_to_lower && calc_clk < cur_clk) || calc_clk > cur_clk); +-} +- +-static void dce110_fill_display_configs( ++void dce110_fill_display_configs( + const struct dc_state *context, + struct dm_pp_display_configuration *pp_display_cfg) + { +@@ -644,197 +611,6 @@ static void dce11_pplib_apply_display_requirements( + dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); + } + +-static void dcn1_pplib_apply_display_requirements( +- struct dc *dc, +- struct dc_state *context) +-{ +- struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; +- +- pp_display_cfg->min_engine_clock_khz = dc->res_pool->dccg->clks.dcfclk_khz; +- pp_display_cfg->min_memory_clock_khz = dc->res_pool->dccg->clks.fclk_khz; +- pp_display_cfg->min_engine_clock_deep_sleep_khz = dc->res_pool->dccg->clks.dcfclk_deep_sleep_khz; +- pp_display_cfg->min_dcfc_deep_sleep_clock_khz = dc->res_pool->dccg->clks.dcfclk_deep_sleep_khz; +- pp_display_cfg->min_dcfclock_khz = dc->res_pool->dccg->clks.dcfclk_khz; +- pp_display_cfg->disp_clk_khz = dc->res_pool->dccg->clks.dispclk_khz; +- dce110_fill_display_configs(context, pp_display_cfg); +- +- if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) +- dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); +-} +- +-#ifdef CONFIG_X86 +-static int dcn1_determine_dppclk_threshold(struct dccg *dccg, struct dc_clocks *new_clocks) +-{ +- bool request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz; +- bool dispclk_increase = new_clocks->dispclk_khz > dccg->clks.dispclk_khz; +- int disp_clk_threshold = new_clocks->max_supported_dppclk_khz; +- bool cur_dpp_div = dccg->clks.dispclk_khz > dccg->clks.dppclk_khz; +- +- /* increase clock, looking for div is 0 for current, request div is 1*/ +- if (dispclk_increase) { +- /* already divided by 2, no need to reach target clk with 2 steps*/ +- if (cur_dpp_div) +- return new_clocks->dispclk_khz; +- +- /* request disp clk is lower than maximum supported dpp clk, +- * no need to reach target clk with two steps. +- */ +- if (new_clocks->dispclk_khz <= disp_clk_threshold) +- return new_clocks->dispclk_khz; +- +- /* target dpp clk not request divided by 2, still within threshold */ +- if (!request_dpp_div) +- return new_clocks->dispclk_khz; +- +- } else { +- /* decrease clock, looking for current dppclk divided by 2, +- * request dppclk not divided by 2. +- */ +- +- /* current dpp clk not divided by 2, no need to ramp*/ +- if (!cur_dpp_div) +- return new_clocks->dispclk_khz; +- +- /* current disp clk is lower than current maximum dpp clk, +- * no need to ramp +- */ +- if (dccg->clks.dispclk_khz <= disp_clk_threshold) +- return new_clocks->dispclk_khz; +- +- /* request dpp clk need to be divided by 2 */ +- if (request_dpp_div) +- return new_clocks->dispclk_khz; +- } +- +- return disp_clk_threshold; +-} +- +-static void dcn1_ramp_up_dispclk_with_dpp(struct dccg *dccg, struct dc_clocks *new_clocks) +-{ +- struct dc *dc = dccg->ctx->dc; +- int dispclk_to_dpp_threshold = dcn1_determine_dppclk_threshold(dccg, new_clocks); +- bool request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz; +- int i; +- +- /* set disp clk to dpp clk threshold */ +- dce112_set_clock(dccg, dispclk_to_dpp_threshold); +- +- /* update request dpp clk division option */ +- for (i = 0; i < dc->res_pool->pipe_count; i++) { +- struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; +- +- if (!pipe_ctx->plane_state) +- continue; +- +- pipe_ctx->plane_res.dpp->funcs->dpp_dppclk_control( +- pipe_ctx->plane_res.dpp, +- request_dpp_div, +- true); +- } +- +- /* If target clk not same as dppclk threshold, set to target clock */ +- if (dispclk_to_dpp_threshold != new_clocks->dispclk_khz) +- dce112_set_clock(dccg, new_clocks->dispclk_khz); +- +- dccg->clks.dispclk_khz = new_clocks->dispclk_khz; +- dccg->clks.dppclk_khz = new_clocks->dppclk_khz; +- dccg->clks.max_supported_dppclk_khz = new_clocks->max_supported_dppclk_khz; +-} +- +-static void dcn1_update_clocks(struct dccg *dccg, +- struct dc_state *context, +- bool safe_to_lower) +-{ +- struct dc *dc = dccg->ctx->dc; +- struct dc_clocks *new_clocks = &context->bw.dcn.clk; +- struct pp_smu_display_requirement_rv *smu_req_cur = +- &dc->res_pool->pp_smu_req; +- struct pp_smu_display_requirement_rv smu_req = *smu_req_cur; +- struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu; +- struct dm_pp_clock_for_voltage_req clock_voltage_req = {0}; +- bool send_request_to_increase = false; +- bool send_request_to_lower = false; +- +- if (new_clocks->phyclk_khz) +- smu_req.display_count = 1; +- else +- smu_req.display_count = 0; +- +- if (new_clocks->dispclk_khz > dccg->clks.dispclk_khz +- || new_clocks->phyclk_khz > dccg->clks.phyclk_khz +- || new_clocks->fclk_khz > dccg->clks.fclk_khz +- || new_clocks->dcfclk_khz > dccg->clks.dcfclk_khz) +- send_request_to_increase = true; +- +- if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, dccg->clks.phyclk_khz)) { +- dccg->clks.phyclk_khz = new_clocks->phyclk_khz; +- +- send_request_to_lower = true; +- } +- +- if (should_set_clock(safe_to_lower, new_clocks->fclk_khz, dccg->clks.fclk_khz)) { +- dccg->clks.fclk_khz = new_clocks->fclk_khz; +- clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_FCLK; +- clock_voltage_req.clocks_in_khz = new_clocks->fclk_khz; +- smu_req.hard_min_fclk_khz = new_clocks->fclk_khz; +- +- dm_pp_apply_clock_for_voltage_request(dccg->ctx, &clock_voltage_req); +- send_request_to_lower = true; +- } +- +- if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, dccg->clks.dcfclk_khz)) { +- dccg->clks.dcfclk_khz = new_clocks->dcfclk_khz; +- smu_req.hard_min_dcefclk_khz = new_clocks->dcfclk_khz; +- +- send_request_to_lower = true; +- } +- +- if (should_set_clock(safe_to_lower, +- new_clocks->dcfclk_deep_sleep_khz, dccg->clks.dcfclk_deep_sleep_khz)) { +- dccg->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; +- smu_req.min_deep_sleep_dcefclk_mhz = new_clocks->dcfclk_deep_sleep_khz; +- +- send_request_to_lower = true; +- } +- +- /* make sure dcf clk is before dpp clk to +- * make sure we have enough voltage to run dpp clk +- */ +- if (send_request_to_increase) { +- /*use dcfclk to request voltage*/ +- clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; +- clock_voltage_req.clocks_in_khz = dcn_find_dcfclk_suits_all(dc, new_clocks); +- dm_pp_apply_clock_for_voltage_request(dccg->ctx, &clock_voltage_req); +- if (pp_smu->set_display_requirement) +- pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req); +- dcn1_pplib_apply_display_requirements(dc, context); +- } +- +- /* dcn1 dppclk is tied to dispclk */ +- /* program dispclk on = as a w/a for sleep resume clock ramping issues */ +- if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, dccg->clks.dispclk_khz) +- || new_clocks->dispclk_khz == dccg->clks.dispclk_khz) { +- dcn1_ramp_up_dispclk_with_dpp(dccg, new_clocks); +- dccg->clks.dispclk_khz = new_clocks->dispclk_khz; +- +- send_request_to_lower = true; +- } +- +- if (!send_request_to_increase && send_request_to_lower) { +- /*use dcfclk to request voltage*/ +- clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; +- clock_voltage_req.clocks_in_khz = dcn_find_dcfclk_suits_all(dc, new_clocks); +- dm_pp_apply_clock_for_voltage_request(dccg->ctx, &clock_voltage_req); +- if (pp_smu->set_display_requirement) +- pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req); +- dcn1_pplib_apply_display_requirements(dc, context); +- } +- +- +- *smu_req_cur = smu_req; +-} +-#endif +- + static void dce_update_clocks(struct dccg *dccg, + struct dc_state *context, + bool safe_to_lower) +@@ -942,13 +718,6 @@ static void dce12_update_clocks(struct dccg *dccg, + context->bw.dce.dispclk_khz = unpatched_disp_clk; + } + +-#ifdef CONFIG_DRM_AMD_DC_DCN1_0 +-static const struct dccg_funcs dcn1_funcs = { +- .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, +- .update_clocks = dcn1_update_clocks +-}; +-#endif +- + static const struct dccg_funcs dce120_funcs = { + .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, + .update_clocks = dce12_update_clocks +@@ -1098,48 +867,6 @@ struct dccg *dce120_dccg_create(struct dc_context *ctx) + return &dccg_dce->base; + } + +-#ifdef CONFIG_X86 +-struct dccg *dcn1_dccg_create(struct dc_context *ctx) +-{ +- struct dc_debug_options *debug = &ctx->dc->debug; +- struct dc_bios *bp = ctx->dc_bios; +- struct dc_firmware_info fw_info = { { 0 } }; +- struct dce_dccg *dccg_dce = kzalloc(sizeof(*dccg_dce), GFP_KERNEL); +- +- if (dccg_dce == NULL) { +- BREAK_TO_DEBUGGER(); +- return NULL; +- } +- +- dccg_dce->base.ctx = ctx; +- dccg_dce->base.funcs = &dcn1_funcs; +- +- dccg_dce->dfs_bypass_disp_clk = 0; +- +- dccg_dce->dprefclk_ss_percentage = 0; +- dccg_dce->dprefclk_ss_divider = 1000; +- dccg_dce->ss_on_dprefclk = false; +- +- dccg_dce->dprefclk_khz = 600000; +- if (bp->integrated_info) +- dccg_dce->dentist_vco_freq_khz = bp->integrated_info->dentist_vco_freq; +- if (dccg_dce->dentist_vco_freq_khz == 0) { +- bp->funcs->get_firmware_info(bp, &fw_info); +- dccg_dce->dentist_vco_freq_khz = fw_info.smu_gpu_pll_output_freq; +- if (dccg_dce->dentist_vco_freq_khz == 0) +- dccg_dce->dentist_vco_freq_khz = 3600000; +- } +- +- if (!debug->disable_dfs_bypass && bp->integrated_info) +- if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) +- dccg_dce->dfs_bypass_enabled = true; +- +- dce_clock_read_ss_info(dccg_dce); +- +- return &dccg_dce->base; +-} +-#endif +- + void dce_dccg_destroy(struct dccg **dccg) + { + struct dce_dccg *dccg_dce = TO_DCE_DCCG(*dccg); +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_dccg.h +similarity index 74% +rename from drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +rename to drivers/gpu/drm/amd/display/dc/dce/dce_dccg.h +index 8f902f2e74f4..786d96319e7a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h ++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dccg.h +@@ -24,10 +24,10 @@ + */ + + +-#ifndef _DCE_CLOCKS_H_ +-#define _DCE_CLOCKS_H_ ++#ifndef _DCE_DCCG_H_ ++#define _DCE_DCCG_H_ + +-#include "display_clock.h" ++#include "dccg.h" + + #define MEMORY_TYPE_MULTIPLIER_CZ 4 + +@@ -103,6 +103,42 @@ struct dce_dccg { + enum dm_pp_clocks_state cur_min_clks_state; + }; + ++/* Starting DID for each range */ ++enum dentist_base_divider_id { ++ DENTIST_BASE_DID_1 = 0x08, ++ DENTIST_BASE_DID_2 = 0x40, ++ DENTIST_BASE_DID_3 = 0x60, ++ DENTIST_BASE_DID_4 = 0x7e, ++ DENTIST_MAX_DID = 0x7f ++}; ++ ++/* Starting point and step size for each divider range.*/ ++enum dentist_divider_range { ++ DENTIST_DIVIDER_RANGE_1_START = 8, /* 2.00 */ ++ DENTIST_DIVIDER_RANGE_1_STEP = 1, /* 0.25 */ ++ DENTIST_DIVIDER_RANGE_2_START = 64, /* 16.00 */ ++ DENTIST_DIVIDER_RANGE_2_STEP = 2, /* 0.50 */ ++ DENTIST_DIVIDER_RANGE_3_START = 128, /* 32.00 */ ++ DENTIST_DIVIDER_RANGE_3_STEP = 4, /* 1.00 */ ++ DENTIST_DIVIDER_RANGE_4_START = 248, /* 62.00 */ ++ DENTIST_DIVIDER_RANGE_4_STEP = 264, /* 66.00 */ ++ DENTIST_DIVIDER_RANGE_SCALE_FACTOR = 4 ++}; ++ ++static inline bool should_set_clock(bool safe_to_lower, int calc_clk, int cur_clk) ++{ ++ return ((safe_to_lower && calc_clk < cur_clk) || calc_clk > cur_clk); ++} ++ ++void dce_clock_read_ss_info(struct dce_dccg *dccg_dce); ++ ++int dce12_get_dp_ref_freq_khz(struct dccg *dccg); ++ ++void dce110_fill_display_configs( ++ const struct dc_state *context, ++ struct dm_pp_display_configuration *pp_display_cfg); ++ ++int dce112_set_clock(struct dccg *dccg, int requested_clk_khz); + + struct dccg *dce_dccg_create( + struct dc_context *ctx, +@@ -124,10 +160,6 @@ struct dccg *dce112_dccg_create( + + struct dccg *dce120_dccg_create(struct dc_context *ctx); + +-#ifdef CONFIG_X86 +-struct dccg *dcn1_dccg_create(struct dc_context *ctx); +-#endif +- + void dce_dccg_destroy(struct dccg **dccg); + +-#endif /* _DCE_CLOCKS_H_ */ ++#endif /* _DCE_DCCG_H_ */ +diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +index 5d6256177066..36015f7cfb96 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c +@@ -22,7 +22,7 @@ + * Authors: AMD + * + */ +-#include "../dce/dce_clocks.h" ++#include "../dce/dce_dccg.h" + #include "dm_services.h" + + #include "link_encoder.h" +diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +index 18f9135c9365..d78b06470865 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +@@ -31,7 +31,7 @@ + #include "resource.h" + #include "dce110/dce110_resource.h" + +-#include "../dce/dce_clocks.h" ++#include "../dce/dce_dccg.h" + #include "include/irq_service_interface.h" + #include "dce/dce_audio.h" + #include "dce110/dce110_timing_generator.h" +diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +index cc48a871151e..b3d00d7e51fa 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c +@@ -23,7 +23,7 @@ + * + */ + +-#include "../dce/dce_clocks.h" ++#include "../dce/dce_dccg.h" + #include "dm_services.h" + + #include "link_encoder.h" +diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +index da2d50d2d720..512a22d9fea8 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c +@@ -32,7 +32,7 @@ + #include "include/irq_service_interface.h" + #include "dce120_resource.h" + +-#include "../dce/dce_clocks.h" ++#include "../dce/dce_dccg.h" + #include "dce112/dce112_resource.h" + + #include "dce110/dce110_resource.h" +diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +index 313141b532e0..1fccb5230296 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c +@@ -23,7 +23,7 @@ + * + */ + +-#include "../dce/dce_clocks.h" ++#include "../dce/dce_dccg.h" + #include "dce/dce_8_0_d.h" + #include "dce/dce_8_0_sh_mask.h" + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +index 032f872be89c..e13ab66a161a 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +@@ -24,7 +24,7 @@ + + DCN10 = dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o dcn10_hw_sequencer_debug.o \ + dcn10_dpp.o dcn10_opp.o dcn10_optc.o \ +- dcn10_hubp.o dcn10_mpc.o \ ++ dcn10_hubp.o dcn10_mpc.o dcn10_dccg.o \ + dcn10_dpp_dscl.o dcn10_dpp_cm.o dcn10_cm_common.o \ + dcn10_hubbub.o dcn10_stream_encoder.o dcn10_link_encoder.o + +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dccg.c +new file mode 100644 +index 000000000000..abfe82f02fd8 +--- /dev/null ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dccg.c +@@ -0,0 +1,278 @@ ++/* ++ * Copyright 2018 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 ++ * ++ */ ++ ++#include "dcn10_dccg.h" ++ ++#include "reg_helper.h" ++#include "core_types.h" ++ ++#define TO_DCE_DCCG(clocks)\ ++ container_of(clocks, struct dce_dccg, base) ++ ++#define REG(reg) \ ++ (dccg_dce->regs->reg) ++ ++#undef FN ++#define FN(reg_name, field_name) \ ++ dccg_dce->dccg_shift->field_name, dccg_dce->dccg_mask->field_name ++ ++#define CTX \ ++ dccg_dce->base.ctx ++#define DC_LOGGER \ ++ dccg->ctx->logger ++ ++void dcn1_pplib_apply_display_requirements( ++ struct dc *dc, ++ struct dc_state *context) ++{ ++ struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg; ++ ++ pp_display_cfg->min_engine_clock_khz = dc->res_pool->dccg->clks.dcfclk_khz; ++ pp_display_cfg->min_memory_clock_khz = dc->res_pool->dccg->clks.fclk_khz; ++ pp_display_cfg->min_engine_clock_deep_sleep_khz = dc->res_pool->dccg->clks.dcfclk_deep_sleep_khz; ++ pp_display_cfg->min_dcfc_deep_sleep_clock_khz = dc->res_pool->dccg->clks.dcfclk_deep_sleep_khz; ++ pp_display_cfg->min_dcfclock_khz = dc->res_pool->dccg->clks.dcfclk_khz; ++ pp_display_cfg->disp_clk_khz = dc->res_pool->dccg->clks.dispclk_khz; ++ dce110_fill_display_configs(context, pp_display_cfg); ++ ++ if (memcmp(&dc->current_state->pp_display_cfg, pp_display_cfg, sizeof(*pp_display_cfg)) != 0) ++ dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg); ++} ++ ++static int dcn1_determine_dppclk_threshold(struct dccg *dccg, struct dc_clocks *new_clocks) ++{ ++ bool request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz; ++ bool dispclk_increase = new_clocks->dispclk_khz > dccg->clks.dispclk_khz; ++ int disp_clk_threshold = new_clocks->max_supported_dppclk_khz; ++ bool cur_dpp_div = dccg->clks.dispclk_khz > dccg->clks.dppclk_khz; ++ ++ /* increase clock, looking for div is 0 for current, request div is 1*/ ++ if (dispclk_increase) { ++ /* already divided by 2, no need to reach target clk with 2 steps*/ ++ if (cur_dpp_div) ++ return new_clocks->dispclk_khz; ++ ++ /* request disp clk is lower than maximum supported dpp clk, ++ * no need to reach target clk with two steps. ++ */ ++ if (new_clocks->dispclk_khz <= disp_clk_threshold) ++ return new_clocks->dispclk_khz; ++ ++ /* target dpp clk not request divided by 2, still within threshold */ ++ if (!request_dpp_div) ++ return new_clocks->dispclk_khz; ++ ++ } else { ++ /* decrease clock, looking for current dppclk divided by 2, ++ * request dppclk not divided by 2. ++ */ ++ ++ /* current dpp clk not divided by 2, no need to ramp*/ ++ if (!cur_dpp_div) ++ return new_clocks->dispclk_khz; ++ ++ /* current disp clk is lower than current maximum dpp clk, ++ * no need to ramp ++ */ ++ if (dccg->clks.dispclk_khz <= disp_clk_threshold) ++ return new_clocks->dispclk_khz; ++ ++ /* request dpp clk need to be divided by 2 */ ++ if (request_dpp_div) ++ return new_clocks->dispclk_khz; ++ } ++ ++ return disp_clk_threshold; ++} ++ ++static void dcn1_ramp_up_dispclk_with_dpp(struct dccg *dccg, struct dc_clocks *new_clocks) ++{ ++ struct dc *dc = dccg->ctx->dc; ++ int dispclk_to_dpp_threshold = dcn1_determine_dppclk_threshold(dccg, new_clocks); ++ bool request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz; ++ int i; ++ ++ /* set disp clk to dpp clk threshold */ ++ dce112_set_clock(dccg, dispclk_to_dpp_threshold); ++ ++ /* update request dpp clk division option */ ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i]; ++ ++ if (!pipe_ctx->plane_state) ++ continue; ++ ++ pipe_ctx->plane_res.dpp->funcs->dpp_dppclk_control( ++ pipe_ctx->plane_res.dpp, ++ request_dpp_div, ++ true); ++ } ++ ++ /* If target clk not same as dppclk threshold, set to target clock */ ++ if (dispclk_to_dpp_threshold != new_clocks->dispclk_khz) ++ dce112_set_clock(dccg, new_clocks->dispclk_khz); ++ ++ dccg->clks.dispclk_khz = new_clocks->dispclk_khz; ++ dccg->clks.dppclk_khz = new_clocks->dppclk_khz; ++ dccg->clks.max_supported_dppclk_khz = new_clocks->max_supported_dppclk_khz; ++} ++ ++static void dcn1_update_clocks(struct dccg *dccg, ++ struct dc_state *context, ++ bool safe_to_lower) ++{ ++ struct dc *dc = dccg->ctx->dc; ++ struct dc_clocks *new_clocks = &context->bw.dcn.clk; ++ struct pp_smu_display_requirement_rv *smu_req_cur = ++ &dc->res_pool->pp_smu_req; ++ struct pp_smu_display_requirement_rv smu_req = *smu_req_cur; ++ struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu; ++ struct dm_pp_clock_for_voltage_req clock_voltage_req = {0}; ++ bool send_request_to_increase = false; ++ bool send_request_to_lower = false; ++ ++ if (new_clocks->phyclk_khz) ++ smu_req.display_count = 1; ++ else ++ smu_req.display_count = 0; ++ ++ if (new_clocks->dispclk_khz > dccg->clks.dispclk_khz ++ || new_clocks->phyclk_khz > dccg->clks.phyclk_khz ++ || new_clocks->fclk_khz > dccg->clks.fclk_khz ++ || new_clocks->dcfclk_khz > dccg->clks.dcfclk_khz) ++ send_request_to_increase = true; ++ ++ if (should_set_clock(safe_to_lower, new_clocks->phyclk_khz, dccg->clks.phyclk_khz)) { ++ dccg->clks.phyclk_khz = new_clocks->phyclk_khz; ++ ++ send_request_to_lower = true; ++ } ++ ++ if (should_set_clock(safe_to_lower, new_clocks->fclk_khz, dccg->clks.fclk_khz)) { ++ dccg->clks.fclk_khz = new_clocks->fclk_khz; ++ clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_FCLK; ++ clock_voltage_req.clocks_in_khz = new_clocks->fclk_khz; ++ smu_req.hard_min_fclk_khz = new_clocks->fclk_khz; ++ ++ dm_pp_apply_clock_for_voltage_request(dccg->ctx, &clock_voltage_req); ++ send_request_to_lower = true; ++ } ++ ++ if (should_set_clock(safe_to_lower, new_clocks->dcfclk_khz, dccg->clks.dcfclk_khz)) { ++ dccg->clks.dcfclk_khz = new_clocks->dcfclk_khz; ++ smu_req.hard_min_dcefclk_khz = new_clocks->dcfclk_khz; ++ ++ send_request_to_lower = true; ++ } ++ ++ if (should_set_clock(safe_to_lower, ++ new_clocks->dcfclk_deep_sleep_khz, dccg->clks.dcfclk_deep_sleep_khz)) { ++ dccg->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; ++ smu_req.min_deep_sleep_dcefclk_mhz = new_clocks->dcfclk_deep_sleep_khz; ++ ++ send_request_to_lower = true; ++ } ++ ++ /* make sure dcf clk is before dpp clk to ++ * make sure we have enough voltage to run dpp clk ++ */ ++ if (send_request_to_increase) { ++ /*use dcfclk to request voltage*/ ++ clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; ++ clock_voltage_req.clocks_in_khz = dcn_find_dcfclk_suits_all(dc, new_clocks); ++ dm_pp_apply_clock_for_voltage_request(dccg->ctx, &clock_voltage_req); ++ if (pp_smu->set_display_requirement) ++ pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req); ++ dcn1_pplib_apply_display_requirements(dc, context); ++ } ++ ++ /* dcn1 dppclk is tied to dispclk */ ++ /* program dispclk on = as a w/a for sleep resume clock ramping issues */ ++ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, dccg->clks.dispclk_khz) ++ || new_clocks->dispclk_khz == dccg->clks.dispclk_khz) { ++ dcn1_ramp_up_dispclk_with_dpp(dccg, new_clocks); ++ dccg->clks.dispclk_khz = new_clocks->dispclk_khz; ++ ++ send_request_to_lower = true; ++ } ++ ++ if (!send_request_to_increase && send_request_to_lower) { ++ /*use dcfclk to request voltage*/ ++ clock_voltage_req.clk_type = DM_PP_CLOCK_TYPE_DCFCLK; ++ clock_voltage_req.clocks_in_khz = dcn_find_dcfclk_suits_all(dc, new_clocks); ++ dm_pp_apply_clock_for_voltage_request(dccg->ctx, &clock_voltage_req); ++ if (pp_smu->set_display_requirement) ++ pp_smu->set_display_requirement(&pp_smu->pp_smu, &smu_req); ++ dcn1_pplib_apply_display_requirements(dc, context); ++ } ++ ++ ++ *smu_req_cur = smu_req; ++} ++ ++static const struct dccg_funcs dcn1_funcs = { ++ .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz, ++ .update_clocks = dcn1_update_clocks ++}; ++ ++struct dccg *dcn1_dccg_create(struct dc_context *ctx) ++{ ++ struct dc_debug_options *debug = &ctx->dc->debug; ++ struct dc_bios *bp = ctx->dc_bios; ++ struct dc_firmware_info fw_info = { { 0 } }; ++ struct dce_dccg *dccg_dce = kzalloc(sizeof(*dccg_dce), GFP_KERNEL); ++ ++ if (dccg_dce == NULL) { ++ BREAK_TO_DEBUGGER(); ++ return NULL; ++ } ++ ++ dccg_dce->base.ctx = ctx; ++ dccg_dce->base.funcs = &dcn1_funcs; ++ ++ dccg_dce->dfs_bypass_disp_clk = 0; ++ ++ dccg_dce->dprefclk_ss_percentage = 0; ++ dccg_dce->dprefclk_ss_divider = 1000; ++ dccg_dce->ss_on_dprefclk = false; ++ ++ dccg_dce->dprefclk_khz = 600000; ++ if (bp->integrated_info) ++ dccg_dce->dentist_vco_freq_khz = bp->integrated_info->dentist_vco_freq; ++ if (dccg_dce->dentist_vco_freq_khz == 0) { ++ bp->funcs->get_firmware_info(bp, &fw_info); ++ dccg_dce->dentist_vco_freq_khz = fw_info.smu_gpu_pll_output_freq; ++ if (dccg_dce->dentist_vco_freq_khz == 0) ++ dccg_dce->dentist_vco_freq_khz = 3600000; ++ } ++ ++ if (!debug->disable_dfs_bypass && bp->integrated_info) ++ if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) ++ dccg_dce->dfs_bypass_enabled = true; ++ ++ dce_clock_read_ss_info(dccg_dce); ++ ++ return &dccg_dce->base; ++} +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dccg.h +new file mode 100644 +index 000000000000..7f3dd84be872 +--- /dev/null ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dccg.h +@@ -0,0 +1,37 @@ ++/* ++ * Copyright 2018 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 __DCN10_DCCG_H__ ++#define __DCN10_DCCG_H__ ++ ++#include "../dce/dce_dccg.h" ++ ++void dcn1_pplib_apply_display_requirements( ++ struct dc *dc, ++ struct dc_state *context); ++ ++struct dccg *dcn1_dccg_create(struct dc_context *ctx); ++ ++#endif //__DCN10_DCCG_H__ +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 6227db6b8abc..55d2d1766c24 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +@@ -40,7 +40,7 @@ + #include "dcn10/dcn10_opp.h" + #include "dcn10/dcn10_link_encoder.h" + #include "dcn10/dcn10_stream_encoder.h" +-#include "../dce/dce_clocks.h" ++#include "dcn10/dcn10_dccg.h" + #include "dce/dce_clock_source.h" + #include "dce/dce_audio.h" + #include "dce/dce_hwseq.h" +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 5c050a5a0309..3a394a5e56a6 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h +@@ -82,7 +82,7 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option); + + void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); + /********** DAL Core*********************/ +-#include "display_clock.h" ++#include "hw/dccg.h" + #include "transform.h" + #include "dpp.h" + +diff --git a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +index e688eb9b975c..ac9b4906dd05 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/dcn_calcs.h +@@ -31,8 +31,8 @@ + #define __DCN_CALCS_H__ + + #include "bw_fixed.h" +-#include "display_clock.h" + #include "../dml/display_mode_lib.h" ++#include "hw/dccg.h" + + struct dc; + struct dc_state; +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +similarity index 94% +rename from drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h +rename to drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +index e1ec42bd0e2a..6fd923d876dc 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw/display_clock.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h +@@ -23,8 +23,8 @@ + * + */ + +-#ifndef __DISPLAY_CLOCK_H__ +-#define __DISPLAY_CLOCK_H__ ++#ifndef __DAL_DCCG_H__ ++#define __DAL_DCCG_H__ + + #include "dm_services_types.h" + #include "dc.h" +@@ -44,4 +44,4 @@ struct dccg_funcs { + int (*get_dp_ref_clk_frequency)(struct dccg *dccg); + }; + +-#endif /* __DISPLAY_CLOCK_H__ */ ++#endif /* __DAL_DCCG_H__ */ +-- +2.17.1 + |