diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/4767-drm-amd-display-clean-up-dccg-divider-calc-and-dcn-c.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/4767-drm-amd-display-clean-up-dccg-divider-calc-and-dcn-c.patch | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/4767-drm-amd-display-clean-up-dccg-divider-calc-and-dcn-c.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/4767-drm-amd-display-clean-up-dccg-divider-calc-and-dcn-c.patch new file mode 100644 index 00000000..a25bcaa5 --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/4767-drm-amd-display-clean-up-dccg-divider-calc-and-dcn-c.patch @@ -0,0 +1,334 @@ +From a719cef7c38dbdad11c09ec745797aac170f64f9 Mon Sep 17 00:00:00 2001 +From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> +Date: Thu, 24 May 2018 15:50:18 -0400 +Subject: [PATCH 4767/5725] drm/amd/display: clean up dccg divider calc and dcn + constructor + +No functional change. + +Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> +Reviewed-by: Tony Cheng <Tony.Cheng@amd.com> +Acked-by: Harry Wentland <harry.wentland@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 197 ++++++++---------------- + drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h | 26 ---- + 2 files changed, 68 insertions(+), 155 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +index 55f533cf..6e3bfdf 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c ++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c +@@ -101,90 +101,42 @@ static const struct state_dependent_clocks dce120_max_clks_by_state[] = { + /*ClocksStatePerformance*/ + { .display_clk_khz = 1133000, .pixel_clk_khz = 600000 } }; + +-/* Starting point for each divider range.*/ +-enum dce_divider_range_start { +- DIVIDER_RANGE_01_START = 200, /* 2.00*/ +- DIVIDER_RANGE_02_START = 1600, /* 16.00*/ +- DIVIDER_RANGE_03_START = 3200, /* 32.00*/ +- DIVIDER_RANGE_SCALE_FACTOR = 100 /* Results are scaled up by 100.*/ ++/* Starting DID for each range */ ++enum dentist_base_divider_id { ++ dentist_base_divider_id_1 = 0x08, ++ dentist_base_divider_id_2 = 0x40, ++ dentist_base_divider_id_3 = 0x60, ++ dentist_max_divider_id = 0x80 + }; + +-/* Ranges for divider identifiers (Divider ID or DID) +- mmDENTIST_DISPCLK_CNTL.DENTIST_DISPCLK_WDIVIDER*/ +-enum dce_divider_id_register_setting { +- DIVIDER_RANGE_01_BASE_DIVIDER_ID = 0X08, +- DIVIDER_RANGE_02_BASE_DIVIDER_ID = 0X40, +- DIVIDER_RANGE_03_BASE_DIVIDER_ID = 0X60, +- DIVIDER_RANGE_MAX_DIVIDER_ID = 0X80 ++/* 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_scale_factor = 4 + }; + +-/* Step size between each divider within a range. +- Incrementing the DENTIST_DISPCLK_WDIVIDER by one +- will increment the divider by this much.*/ +-enum dce_divider_range_step_size { +- DIVIDER_RANGE_01_STEP_SIZE = 25, /* 0.25*/ +- DIVIDER_RANGE_02_STEP_SIZE = 50, /* 0.50*/ +- DIVIDER_RANGE_03_STEP_SIZE = 100 /* 1.00 */ +-}; +- +-static bool dce_divider_range_construct( +- struct dce_divider_range *div_range, +- int range_start, +- int range_step, +- int did_min, +- int did_max) +-{ +- div_range->div_range_start = range_start; +- div_range->div_range_step = range_step; +- div_range->did_min = did_min; +- div_range->did_max = did_max; +- +- if (div_range->div_range_step == 0) { +- div_range->div_range_step = 1; +- /*div_range_step cannot be zero*/ +- BREAK_TO_DEBUGGER(); +- } +- /* Calculate this based on the other inputs.*/ +- /* See DividerRange.h for explanation of */ +- /* the relationship between divider id (DID) and a divider.*/ +- /* Number of Divider IDs = (Maximum Divider ID - Minimum Divider ID)*/ +- /* Maximum divider identified in this range = +- * (Number of Divider IDs)*Step size between dividers +- * + The start of this range.*/ +- div_range->div_range_end = (did_max - did_min) * range_step +- + range_start; +- return true; +-} +- +-static int dce_divider_range_calc_divider( +- struct dce_divider_range *div_range, +- int did) +-{ +- /* Is this DID within our range?*/ +- if ((did < div_range->did_min) || (did >= div_range->did_max)) +- return INVALID_DIVIDER; +- +- return ((did - div_range->did_min) * div_range->div_range_step) +- + div_range->div_range_start; +- +-} +- +-static int dce_divider_range_get_divider( +- struct dce_divider_range *div_range, +- int ranges_num, +- int did) ++static int dentist_get_divider_from_did(int did) + { +- int div = INVALID_DIVIDER; +- int i; +- +- for (i = 0; i < ranges_num; i++) { +- /* Calculate divider with given divider ID*/ +- div = dce_divider_range_calc_divider(&div_range[i], did); +- /* Found a valid return divider*/ +- if (div != INVALID_DIVIDER) +- break; ++ if (did < dentist_base_divider_id_1) ++ did = dentist_base_divider_id_1; ++ if (did > dentist_max_divider_id) ++ did = dentist_max_divider_id; ++ ++ if (did < dentist_base_divider_id_2) { ++ return dentist_divider_range_1_start + dentist_divider_range_1_step ++ * (did - dentist_base_divider_id_1); ++ } else if (did < dentist_base_divider_id_3) { ++ return dentist_divider_range_2_start + dentist_divider_range_2_step ++ * (did - dentist_base_divider_id_2); ++ } else { ++ return dentist_divider_range_3_start + dentist_divider_range_3_step ++ * (did - dentist_base_divider_id_3); + } +- return div; + } + + static int dce_clocks_get_dp_ref_freq(struct dccg *clk) +@@ -193,7 +145,7 @@ static int dce_clocks_get_dp_ref_freq(struct dccg *clk) + int dprefclk_wdivider; + int dprefclk_src_sel; + int dp_ref_clk_khz = 600000; +- int target_div = INVALID_DIVIDER; ++ int target_div; + + /* ASSERT DP Reference Clock source is from DFS*/ + REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel); +@@ -204,16 +156,11 @@ static int dce_clocks_get_dp_ref_freq(struct dccg *clk) + REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider); + + /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ +- target_div = dce_divider_range_get_divider( +- clk_dce->divider_ranges, +- DIVIDER_RANGE_MAX, +- dprefclk_wdivider); +- +- if (target_div != INVALID_DIVIDER) { +- /* Calculate the current DFS clock, in kHz.*/ +- dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR +- * clk_dce->dentist_vco_freq_khz) / target_div; +- } ++ target_div = dentist_get_divider_from_did(dprefclk_wdivider); ++ ++ /* Calculate the current DFS clock, in kHz.*/ ++ dp_ref_clk_khz = (dentist_divider_range_scale_factor ++ * clk_dce->dentist_vco_freq_khz) / target_div; + + /* SW will adjust DP REF Clock average value for all purposes + * (DP DTO / DP Audio DTO and DP GTC) +@@ -229,17 +176,12 @@ static int dce_clocks_get_dp_ref_freq(struct dccg *clk) + */ + if (clk_dce->ss_on_dprefclk && clk_dce->dprefclk_ss_divider != 0) { + struct fixed31_32 ss_percentage = dc_fixpt_div_int( +- dc_fixpt_from_fraction( +- clk_dce->dprefclk_ss_percentage, +- clk_dce->dprefclk_ss_divider), 200); ++ dc_fixpt_from_fraction(clk_dce->dprefclk_ss_percentage, ++ clk_dce->dprefclk_ss_divider), 200); + struct fixed31_32 adj_dp_ref_clk_khz; + +- ss_percentage = dc_fixpt_sub(dc_fixpt_one, +- ss_percentage); +- adj_dp_ref_clk_khz = +- dc_fixpt_mul_int( +- ss_percentage, +- dp_ref_clk_khz); ++ ss_percentage = dc_fixpt_sub(dc_fixpt_one, ss_percentage); ++ adj_dp_ref_clk_khz = dc_fixpt_mul_int(ss_percentage, dp_ref_clk_khz); + dp_ref_clk_khz = dc_fixpt_floor(adj_dp_ref_clk_khz); + } + +@@ -257,17 +199,12 @@ static int dce_clocks_get_dp_ref_freq_wrkaround(struct dccg *clk) + + if (clk_dce->ss_on_dprefclk && clk_dce->dprefclk_ss_divider != 0) { + struct fixed31_32 ss_percentage = dc_fixpt_div_int( +- dc_fixpt_from_fraction( +- clk_dce->dprefclk_ss_percentage, ++ dc_fixpt_from_fraction(clk_dce->dprefclk_ss_percentage, + clk_dce->dprefclk_ss_divider), 200); + struct fixed31_32 adj_dp_ref_clk_khz; + +- ss_percentage = dc_fixpt_sub(dc_fixpt_one, +- ss_percentage); +- adj_dp_ref_clk_khz = +- dc_fixpt_mul_int( +- ss_percentage, +- dp_ref_clk_khz); ++ ss_percentage = dc_fixpt_sub(dc_fixpt_one, ss_percentage); ++ adj_dp_ref_clk_khz = dc_fixpt_mul_int(ss_percentage, dp_ref_clk_khz); + dp_ref_clk_khz = dc_fixpt_floor(adj_dp_ref_clk_khz); + } + +@@ -804,25 +741,6 @@ static void dce_dccg_construct( + + dce_clock_read_integrated_info(clk_dce); + dce_clock_read_ss_info(clk_dce); +- +- dce_divider_range_construct( +- &clk_dce->divider_ranges[DIVIDER_RANGE_01], +- DIVIDER_RANGE_01_START, +- DIVIDER_RANGE_01_STEP_SIZE, +- DIVIDER_RANGE_01_BASE_DIVIDER_ID, +- DIVIDER_RANGE_02_BASE_DIVIDER_ID); +- dce_divider_range_construct( +- &clk_dce->divider_ranges[DIVIDER_RANGE_02], +- DIVIDER_RANGE_02_START, +- DIVIDER_RANGE_02_STEP_SIZE, +- DIVIDER_RANGE_02_BASE_DIVIDER_ID, +- DIVIDER_RANGE_03_BASE_DIVIDER_ID); +- dce_divider_range_construct( +- &clk_dce->divider_ranges[DIVIDER_RANGE_03], +- DIVIDER_RANGE_03_START, +- DIVIDER_RANGE_03_STEP_SIZE, +- DIVIDER_RANGE_03_BASE_DIVIDER_ID, +- DIVIDER_RANGE_MAX_DIVIDER_ID); + } + + struct dccg *dce_dccg_create( +@@ -921,6 +839,9 @@ struct dccg *dce120_dccg_create(struct dc_context *ctx) + + struct dccg *dcn1_dccg_create(struct dc_context *ctx) + { ++ struct dc_debug *debug = &ctx->dc->debug; ++ struct dc_bios *bp = ctx->dc_bios; ++ struct dc_firmware_info fw_info = { { 0 } }; + struct dce_dccg *clk_dce = kzalloc(sizeof(*clk_dce), GFP_KERNEL); + + if (clk_dce == NULL) { +@@ -928,12 +849,30 @@ struct dccg *dcn1_dccg_create(struct dc_context *ctx) + return NULL; + } + +- /* TODO strip out useful stuff out of dce constructor */ +- dce_dccg_construct( +- clk_dce, ctx, NULL, NULL, NULL); +- ++ clk_dce->base.ctx = ctx; + clk_dce->base.funcs = &dcn1_funcs; + ++ clk_dce->dfs_bypass_disp_clk = 0; ++ ++ clk_dce->dprefclk_ss_percentage = 0; ++ clk_dce->dprefclk_ss_divider = 1000; ++ clk_dce->ss_on_dprefclk = false; ++ ++ if (bp->integrated_info) ++ clk_dce->dentist_vco_freq_khz = bp->integrated_info->dentist_vco_freq; ++ if (clk_dce->dentist_vco_freq_khz == 0) { ++ bp->funcs->get_firmware_info(bp, &fw_info); ++ clk_dce->dentist_vco_freq_khz = fw_info.smu_gpu_pll_output_freq; ++ if (clk_dce->dentist_vco_freq_khz == 0) ++ clk_dce->dentist_vco_freq_khz = 3600000; ++ } ++ ++ if (!debug->disable_dfs_bypass && bp->integrated_info) ++ if (bp->integrated_info->gpu_cap_info & DFS_BYPASS_ENABLE) ++ clk_dce->dfs_bypass_enabled = true; ++ ++ dce_clock_read_ss_info(clk_dce); ++ + return &clk_dce->base; + } + +diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +index 7907c3c4..04a9e3c 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h ++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.h +@@ -57,31 +57,6 @@ struct dce_disp_clk_registers { + uint32_t DENTIST_DISPCLK_CNTL; + }; + +-/* Array identifiers and count for the divider ranges.*/ +-enum dce_divider_range_count { +- DIVIDER_RANGE_01 = 0, +- DIVIDER_RANGE_02, +- DIVIDER_RANGE_03, +- DIVIDER_RANGE_MAX /* == 3*/ +-}; +- +-enum dce_divider_error_types { +- INVALID_DID = 0, +- INVALID_DIVIDER = 1 +-}; +- +-struct dce_divider_range { +- int div_range_start; +- /* The end of this range of dividers.*/ +- int div_range_end; +- /* The distance between each divider in this range.*/ +- int div_range_step; +- /* The divider id for the lowest divider.*/ +- int did_min; +- /* The divider id for the highest divider.*/ +- int did_max; +-}; +- + struct dce_dccg { + struct dccg base; + const struct dce_disp_clk_registers *regs; +@@ -89,7 +64,6 @@ struct dce_dccg { + const struct dce_disp_clk_mask *clk_mask; + + struct state_dependent_clocks max_clks_by_state[DM_PP_CLOCKS_MAX_STATES]; +- struct dce_divider_range divider_ranges[DIVIDER_RANGE_MAX]; + + int dentist_vco_freq_khz; + +-- +2.7.4 + |