aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/4767-drm-amd-display-clean-up-dccg-divider-calc-and-dcn-c.patch
diff options
context:
space:
mode:
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.patch334
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
+