From: Dmytro Laktyushkin <Dmytro.Laktyushkin@xxxxxxx> No functional change. Change-Id: Ia108aff1f2e1def6d69cbda13d90b9a818fbecc4 Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin at amd.com> Reviewed-by: Tony Cheng <Tony.Cheng at amd.com> Acked-by: Harry Wentland <harry.wentland at amd.com> --- .../gpu/drm/amd/display/dc/dce/dce_clocks.c | 197 ++++++------------ .../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 55f533cf55ba..6e3bfdf8a9e7 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 7907c3c4b1c1..04a9e3c04aa7 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.17.1