diff options
Diffstat (limited to 'common/recipes-kernel/linux/files/0738-drm-amd-dal-refactor-clock-sources.patch')
-rw-r--r-- | common/recipes-kernel/linux/files/0738-drm-amd-dal-refactor-clock-sources.patch | 4640 |
1 files changed, 4640 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0738-drm-amd-dal-refactor-clock-sources.patch b/common/recipes-kernel/linux/files/0738-drm-amd-dal-refactor-clock-sources.patch new file mode 100644 index 00000000..aa28f490 --- /dev/null +++ b/common/recipes-kernel/linux/files/0738-drm-amd-dal-refactor-clock-sources.patch @@ -0,0 +1,4640 @@ +From d881814e00bd5f40228ea222784cd0d19b5ed381 Mon Sep 17 00:00:00 2001 +From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> +Date: Mon, 25 Jan 2016 16:21:37 -0500 +Subject: [PATCH 0738/1110] drm/amd/dal: refactor clock sources + +Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com> +Acked-by: Harry Wentland <harry.wentland@amd.com> +--- + drivers/gpu/drm/amd/dal/dc/core/dc.c | 2 +- + drivers/gpu/drm/amd/dal/dc/core/dc_link.c | 2 +- + drivers/gpu/drm/amd/dal/dc/core/dc_resource.c | 3 +- + drivers/gpu/drm/amd/dal/dc/dc_types.h | 1 + + .../gpu/drm/amd/dal/dc/dce100/dce100_resource.c | 68 +- + drivers/gpu/drm/amd/dal/dc/dce110/Makefile | 20 +- + .../drm/amd/dal/dc/dce110/dce110_clock_source.c | 1163 ++++++++++++++++++++ + .../drm/amd/dal/dc/dce110/dce110_clock_source.h | 64 ++ + .../drm/amd/dal/dc/dce110/dce110_hw_sequencer.c | 24 +- + .../gpu/drm/amd/dal/dc/dce110/dce110_resource.c | 67 +- + drivers/gpu/drm/amd/dal/dc/gpu/Makefile | 8 +- + .../gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.c | 407 ------- + .../gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.h | 81 -- + drivers/gpu/drm/amd/dal/dc/gpu/clock_source.h | 141 --- + .../dal/dc/gpu/dce110/ext_clock_source_dce110.c | 383 ------- + .../dal/dc/gpu/dce110/ext_clock_source_dce110.h | 38 - + .../dal/dc/gpu/dce110/pll_clock_source_dce110.c | 718 ------------ + .../dal/dc/gpu/dce110/pll_clock_source_dce110.h | 55 - + .../dal/dc/gpu/dce110/vce_clock_source_dce110.c | 193 ---- + .../dal/dc/gpu/dce110/vce_clock_source_dce110.h | 32 - + drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.c | 121 -- + drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.h | 47 - + drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.c | 139 --- + drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.h | 52 - + drivers/gpu/drm/amd/dal/dc/inc/clock_source.h | 176 +++ + drivers/gpu/drm/amd/dal/dc/inc/core_types.h | 2 +- + .../gpu/drm/amd/dal/include/bios_parser_types.h | 1 + + .../drm/amd/dal/include/clock_source_interface.h | 89 -- + .../gpu/drm/amd/dal/include/clock_source_types.h | 113 -- + 29 files changed, 1521 insertions(+), 2689 deletions(-) + create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c + create mode 100644 drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h + delete mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.c + delete mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.h + delete mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/clock_source.h + delete mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.c + delete mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.h + delete mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.c + delete mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.h + delete mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.c + delete mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.h + delete mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.c + delete mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.h + delete mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.c + delete mode 100644 drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.h + create mode 100644 drivers/gpu/drm/amd/dal/dc/inc/clock_source.h + delete mode 100644 drivers/gpu/drm/amd/dal/include/clock_source_interface.h + delete mode 100644 drivers/gpu/drm/amd/dal/include/clock_source_types.h + +diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc.c b/drivers/gpu/drm/amd/dal/dc/core/dc.c +index 0664af2..51a8589 100644 +--- a/drivers/gpu/drm/amd/dal/dc/core/dc.c ++++ b/drivers/gpu/drm/amd/dal/dc/core/dc.c +@@ -33,7 +33,7 @@ + #include "resource.h" + + #include "adapter_service_interface.h" +-#include "clock_source_interface.h" ++#include "clock_source.h" + #include "dc_bios_types.h" + + #include "bandwidth_calcs.h" +diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c +index caba06e..a2879bb 100644 +--- a/drivers/gpu/drm/amd/dal/dc/core/dc_link.c ++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_link.c +@@ -1215,7 +1215,7 @@ static void enable_link_hdmi(struct core_stream *stream) + + link->link_enc->funcs->enable_tmds_output( + link->link_enc, +- dal_clock_source_get_id(stream->clock_source), ++ stream->clock_source->id, + stream->public.timing.display_color_depth, + stream->signal == SIGNAL_TYPE_HDMI_TYPE_A, + stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK, +diff --git a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c +index 2aa8db1..52307cb 100644 +--- a/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c ++++ b/drivers/gpu/drm/amd/dal/dc/core/dc_resource.c +@@ -66,8 +66,7 @@ static bool is_sharable_clk_src( + const struct core_stream *stream_with_clk_src, + const struct core_stream *stream) + { +- enum clock_source_id id = dal_clock_source_get_id( +- stream_with_clk_src->clock_source); ++ enum clock_source_id id = stream_with_clk_src->clock_source->id; + + if (stream_with_clk_src->clock_source == NULL) + return false; +diff --git a/drivers/gpu/drm/amd/dal/dc/dc_types.h b/drivers/gpu/drm/amd/dal/dc/dc_types.h +index c797642..60e5603 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dc_types.h ++++ b/drivers/gpu/drm/amd/dal/dc/dc_types.h +@@ -25,6 +25,7 @@ + #ifndef DC_TYPES_H_ + #define DC_TYPES_H_ + ++#include "dc_services_types.h" + #include "fixed32_32.h" + #include "fixed31_32.h" + #include "irq_types.h" +diff --git a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c +index 7ce1bb4..4027547 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c ++++ b/drivers/gpu/drm/amd/dal/dc/dce100/dce100_resource.c +@@ -37,6 +37,7 @@ + #include "dce110/dce110_transform.h" + #include "dce110/dce110_stream_encoder.h" + #include "dce110/dce110_opp.h" ++#include "dce110/dce110_clock_source.h" + + #include "dce/dce_10_0_d.h" + +@@ -134,6 +135,18 @@ static const struct dce110_mem_input_reg_offsets dce100_mi_reg_offsets[] = { + } + }; + ++ ++static const struct dce110_clk_src_reg_offsets dce100_clk_src_reg_offsets[] = { ++ { ++ .pll_cntl = mmBPHYC_PLL0_PLL_CNTL, ++ .pixclk_resync_cntl = mmPIXCLK0_RESYNC_CNTL ++ }, ++ { ++ .pll_cntl = mmBPHYC_PLL1_PLL_CNTL, ++ .pixclk_resync_cntl = mmPIXCLK1_RESYNC_CNTL ++ } ++}; ++ + static const struct dce110_transform_reg_offsets dce100_xfm_offsets[] = { + { + .scl_offset = (mmSCL0_SCL_CONTROL - mmSCL_CONTROL), +@@ -486,6 +499,31 @@ void dce100_opp_destroy(struct output_pixel_processor **opp) + *opp = NULL; + } + ++struct clock_source *dce100_clock_source_create( ++ struct dc_context *ctx, ++ struct dc_bios *bios, ++ enum clock_source_id id, ++ const struct dce110_clk_src_reg_offsets *offsets) ++{ ++ struct dce110_clk_src *clk_src = ++ dc_service_alloc(ctx, sizeof(struct dce110_clk_src)); ++ ++ if (!clk_src) ++ return NULL; ++ ++ if (dce110_clk_src_construct(clk_src, ctx, bios, id, offsets)) ++ return &clk_src->base; ++ ++ BREAK_TO_DEBUGGER(); ++ return NULL; ++} ++ ++void dce100_clock_source_destroy(struct clock_source **clk_src) ++{ ++ dc_service_free((*clk_src)->ctx, TO_DCE110_CLK_SRC(*clk_src)); ++ *clk_src = NULL; ++} ++ + bool dce100_construct_resource_pool( + struct adapter_service *adapter_serv, + uint8_t num_virtual_links, +@@ -493,7 +531,6 @@ bool dce100_construct_resource_pool( + struct resource_pool *pool) + { + unsigned int i; +- struct clock_source_init_data clk_src_init_data = { 0 }; + struct audio_init_data audio_init_data = { 0 }; + struct dc_context *ctx = dc->ctx; + +@@ -506,22 +543,17 @@ bool dce100_construct_resource_pool( + pool->stream_engines.engine.ENGINE_ID_DIGE = 1; + pool->stream_engines.engine.ENGINE_ID_DIGF = 1; + +- clk_src_init_data.as = adapter_serv; +- clk_src_init_data.ctx = ctx; +- clk_src_init_data.clk_src_id.enum_id = ENUM_ID_1; +- clk_src_init_data.clk_src_id.type = OBJECT_TYPE_CLOCK_SOURCE; ++ pool->clock_sources[DCE100_CLK_SRC_PLL0] = dce100_clock_source_create( ++ ctx, dal_adapter_service_get_bios_parser(adapter_serv), ++ CLOCK_SOURCE_ID_PLL0, &dce100_clk_src_reg_offsets[0]); ++ pool->clock_sources[DCE100_CLK_SRC_PLL1] = dce100_clock_source_create( ++ ctx, dal_adapter_service_get_bios_parser(adapter_serv), ++ CLOCK_SOURCE_ID_PLL1, &dce100_clk_src_reg_offsets[1]); ++ pool->clock_sources[DCE100_CLK_SRC_EXT] = dce100_clock_source_create( ++ ctx, dal_adapter_service_get_bios_parser(adapter_serv), ++ CLOCK_SOURCE_ID_EXTERNAL, &dce100_clk_src_reg_offsets[0]); + pool->clk_src_count = DCE100_CLK_SRC_TOTAL; + +- clk_src_init_data.clk_src_id.id = CLOCK_SOURCE_ID_PLL0; +- pool->clock_sources[DCE100_CLK_SRC_PLL0] = dal_clock_source_create( +- &clk_src_init_data); +- clk_src_init_data.clk_src_id.id = CLOCK_SOURCE_ID_PLL1; +- pool->clock_sources[DCE100_CLK_SRC_PLL1] = dal_clock_source_create( +- &clk_src_init_data); +- clk_src_init_data.clk_src_id.id = CLOCK_SOURCE_ID_EXTERNAL; +- pool->clock_sources[DCE100_CLK_SRC_EXT] = dal_clock_source_create( +- &clk_src_init_data); +- + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] == NULL) { + dal_error("DC: failed to create clock sources!\n"); +@@ -696,7 +728,7 @@ disp_clk_create_fail: + clk_src_create_fail: + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] != NULL) +- dal_clock_source_destroy(&pool->clock_sources[i]); ++ dce100_clock_source_destroy(&pool->clock_sources[i]); + } + return false; + } +@@ -736,7 +768,7 @@ void dce100_destruct_resource_pool(struct resource_pool *pool) + + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] != NULL) +- dal_clock_source_destroy(&pool->clock_sources[i]); ++ dce100_clock_source_destroy(&pool->clock_sources[i]); + } + + for (i = 0; i < pool->audio_count; i++) { +@@ -883,7 +915,7 @@ static enum dc_status build_stream_hw_param(struct core_stream *stream) + stream->max_hdmi_pixel_clock = 600000; + + get_pixel_clock_parameters(stream, &stream->pix_clk_params); +- dal_clock_source_get_pix_clk_dividers( ++ stream->clock_source->funcs->get_pix_clk_dividers( + stream->clock_source, + &stream->pix_clk_params, + &stream->pll_settings); +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/Makefile b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile +index 5bf9b56..ae9d2de 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/Makefile ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/Makefile +@@ -8,26 +8,8 @@ dce110_opp_formatter.o dce110_opp_regamma.o dce110_stream_encoder.o \ + dce110_timing_generator.o dce110_transform.o dce110_transform_gamut.o \ + dce110_transform_scl.o dce110_transform_sclv.o dce110_opp_csc.o\ + dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o \ +-dce110_resource.o dce110_transform_bit_depth.o ++dce110_resource.o dce110_transform_bit_depth.o dce110_clock_source.o + + AMD_DAL_DCE110 = $(addprefix $(AMDDALPATH)/dc/dce110/,$(DCE110)) + + AMD_DAL_FILES += $(AMD_DAL_DCE110) +- +- +-############################################################################### +-# DCE 11x +-############################################################################### +-ifdef 0#CONFIG_DRM_AMD_DAL_DCE11_0 +-TG_DCE110 = dce110_ipp.o dce110_ipp_cursor.o \ +-dce110_ipp_gamma.o dce110_timing_generator.o dce110_link_encoder.o \ +-dce110_opp.o dce110_opp_regamma.o dce110_opp_formatter.o dce110_opp_csc.o \ +-dce110_transform.o dce110_transform_gamut.o dce110_transform_bit_depth.o \ +-dce110_compressor.o dce110_mem_input.o dce110_hw_sequencer.o dce110_resource.o +- +-AMD_DAL_TG_DCE110 = $(addprefix \ +- $(AMDDALPATH)/dc/dce110/,$(TG_DCE110)) +- +-AMD_DAL_FILES += $(AMD_DAL_TG_DCE110) +-endif +- +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c +new file mode 100644 +index 0000000..b096444 +--- /dev/null ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.c +@@ -0,0 +1,1163 @@ ++/* ++ * Copyright 2012-15 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 "dc_services.h" ++ ++/* include DCE11 register header files */ ++#include "dce/dce_11_0_d.h" ++#include "dce/dce_11_0_sh_mask.h" ++ ++#include "dc_types.h" ++#include "core_types.h" ++ ++#include "include/grph_object_id.h" ++#include "include/logger_interface.h" ++ ++#include "dce110_clock_source.h" ++ ++#define FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM 6 ++#define CALC_PLL_CLK_SRC_ERR_TOLERANCE 1 ++#define MAX_PLL_CALC_ERROR 0xFFFFFFFF ++ ++static const struct spread_spectrum_data *get_ss_data_entry( ++ struct dce110_clk_src *clk_src, ++ enum signal_type signal, ++ uint32_t pix_clk_khz) ++{ ++ ++ uint32_t entrys_num; ++ uint32_t i; ++ struct spread_spectrum_data *ss_parm = NULL; ++ struct spread_spectrum_data *ret = NULL; ++ ++ switch (signal) { ++ case SIGNAL_TYPE_DVI_SINGLE_LINK: ++ case SIGNAL_TYPE_DVI_DUAL_LINK: ++ ss_parm = clk_src->dvi_ss_params; ++ entrys_num = clk_src->dvi_ss_params_cnt; ++ break; ++ ++ case SIGNAL_TYPE_HDMI_TYPE_A: ++ ss_parm = clk_src->hdmi_ss_params; ++ entrys_num = clk_src->hdmi_ss_params_cnt; ++ break; ++ ++ case SIGNAL_TYPE_DISPLAY_PORT: ++ case SIGNAL_TYPE_DISPLAY_PORT_MST: ++ case SIGNAL_TYPE_EDP: ++ ss_parm = clk_src->dp_ss_params; ++ entrys_num = clk_src->dp_ss_params_cnt; ++ break; ++ ++ default: ++ ss_parm = NULL; ++ entrys_num = 0; ++ break; ++ } ++ ++ if (ss_parm == NULL) ++ return ret; ++ ++ for (i = 0; i < entrys_num; ++i, ++ss_parm) { ++ if (ss_parm->freq_range_khz >= pix_clk_khz) { ++ ret = ss_parm; ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++/** ++* Function: calculate_fb_and_fractional_fb_divider ++* ++* * DESCRIPTION: Calculates feedback and fractional feedback dividers values ++* ++*PARAMETERS: ++* targetPixelClock Desired frequency in 10 KHz ++* ref_divider Reference divider (already known) ++* postDivider Post Divider (already known) ++* feedback_divider_param Pointer where to store ++* calculated feedback divider value ++* fract_feedback_divider_param Pointer where to store ++* calculated fract feedback divider value ++* ++*RETURNS: ++* It fills the locations pointed by feedback_divider_param ++* and fract_feedback_divider_param ++* It returns - true if feedback divider not 0 ++* - false should never happen) ++*/ ++static bool calculate_fb_and_fractional_fb_divider( ++ struct calc_pll_clock_source *calc_pll_cs, ++ uint32_t target_pix_clk_khz, ++ uint32_t ref_divider, ++ uint32_t post_divider, ++ uint32_t *feedback_divider_param, ++ uint32_t *fract_feedback_divider_param) ++{ ++ uint64_t feedback_divider; ++ ++ feedback_divider = ++ (uint64_t)(target_pix_clk_khz * ref_divider * post_divider); ++ feedback_divider *= 10; ++ /* additional factor, since we divide by 10 afterwards */ ++ feedback_divider *= (uint64_t)(calc_pll_cs->fract_fb_divider_factor); ++ feedback_divider = div_u64(feedback_divider, calc_pll_cs->ref_freq_khz); ++ ++/*Round to the number of precision ++ * The following code replace the old code (ullfeedbackDivider + 5)/10 ++ * for example if the difference between the number ++ * of fractional feedback decimal point and the fractional FB Divider precision ++ * is 2 then the equation becomes (ullfeedbackDivider + 5*100) / (10*100))*/ ++ ++ feedback_divider += (uint64_t) ++ (5 * calc_pll_cs->fract_fb_divider_precision_factor); ++ feedback_divider = ++ div_u64(feedback_divider, ++ calc_pll_cs->fract_fb_divider_precision_factor * 10); ++ feedback_divider *= (uint64_t) ++ (calc_pll_cs->fract_fb_divider_precision_factor); ++ ++ *feedback_divider_param = ++ div_u64_rem( ++ feedback_divider, ++ calc_pll_cs->fract_fb_divider_factor, ++ fract_feedback_divider_param); ++ ++ if (*feedback_divider_param != 0) ++ return true; ++ return false; ++} ++ ++/** ++*calc_fb_divider_checking_tolerance ++* ++*DESCRIPTION: Calculates Feedback and Fractional Feedback divider values ++* for passed Reference and Post divider, checking for tolerance. ++*PARAMETERS: ++* pll_settings Pointer to structure ++* ref_divider Reference divider (already known) ++* postDivider Post Divider (already known) ++* tolerance Tolerance for Calculated Pixel Clock to be within ++* ++*RETURNS: ++* It fills the PLLSettings structure with PLL Dividers values ++* if calculated values are within required tolerance ++* It returns - true if eror is within tolerance ++* - false if eror is not within tolerance ++*/ ++static bool calc_fb_divider_checking_tolerance( ++ struct calc_pll_clock_source *calc_pll_cs, ++ struct pll_settings *pll_settings, ++ uint32_t ref_divider, ++ uint32_t post_divider, ++ uint32_t tolerance) ++{ ++ uint32_t feedback_divider; ++ uint32_t fract_feedback_divider; ++ uint32_t actual_calculated_clock_khz; ++ uint32_t abs_err; ++ uint64_t actual_calc_clk_khz; ++ ++ calculate_fb_and_fractional_fb_divider( ++ calc_pll_cs, ++ pll_settings->adjusted_pix_clk, ++ ref_divider, ++ post_divider, ++ &feedback_divider, ++ &fract_feedback_divider); ++ ++ /*Actual calculated value*/ ++ actual_calc_clk_khz = (uint64_t)(feedback_divider * ++ calc_pll_cs->fract_fb_divider_factor) + ++ fract_feedback_divider; ++ actual_calc_clk_khz *= calc_pll_cs->ref_freq_khz; ++ actual_calc_clk_khz = ++ div_u64(actual_calc_clk_khz, ++ ref_divider * post_divider * ++ calc_pll_cs->fract_fb_divider_factor); ++ ++ actual_calculated_clock_khz = (uint32_t)(actual_calc_clk_khz); ++ ++ abs_err = (actual_calculated_clock_khz > ++ pll_settings->adjusted_pix_clk) ++ ? actual_calculated_clock_khz - ++ pll_settings->adjusted_pix_clk ++ : pll_settings->adjusted_pix_clk - ++ actual_calculated_clock_khz; ++ ++ if (abs_err <= tolerance) { ++ /*found good values*/ ++ pll_settings->reference_freq = calc_pll_cs->ref_freq_khz; ++ pll_settings->reference_divider = ref_divider; ++ pll_settings->feedback_divider = feedback_divider; ++ pll_settings->fract_feedback_divider = fract_feedback_divider; ++ pll_settings->pix_clk_post_divider = post_divider; ++ pll_settings->calculated_pix_clk = ++ actual_calculated_clock_khz; ++ pll_settings->vco_freq = ++ actual_calculated_clock_khz * post_divider; ++ return true; ++ } ++ return false; ++} ++ ++ ++static bool calc_pll_dividers_in_range( ++ struct calc_pll_clock_source *calc_pll_cs, ++ struct pll_settings *pll_settings, ++ uint32_t min_ref_divider, ++ uint32_t max_ref_divider, ++ uint32_t min_post_divider, ++ uint32_t max_post_divider, ++ uint32_t err_tolerance) ++{ ++ uint32_t ref_divider; ++ uint32_t post_divider; ++ uint32_t tolerance; ++ ++/* This is err_tolerance / 10000 = 0.0025 - acceptable error of 0.25% ++ * This is errorTolerance / 10000 = 0.0001 - acceptable error of 0.01%*/ ++ tolerance = (pll_settings->adjusted_pix_clk * err_tolerance) / ++ 10000; ++ if (tolerance < CALC_PLL_CLK_SRC_ERR_TOLERANCE) ++ tolerance = CALC_PLL_CLK_SRC_ERR_TOLERANCE; ++ ++ for ( ++ post_divider = max_post_divider; ++ post_divider >= min_post_divider; ++ --post_divider) { ++ for ( ++ ref_divider = min_ref_divider; ++ ref_divider <= max_ref_divider; ++ ++ref_divider) { ++ if (calc_fb_divider_checking_tolerance( ++ calc_pll_cs, ++ pll_settings, ++ ref_divider, ++ post_divider, ++ tolerance)) { ++ return true; ++ } ++ } ++ } ++ ++ return false; ++} ++ ++static uint32_t calculate_pixel_clock_pll_dividers( ++ struct calc_pll_clock_source *calc_pll_cs, ++ struct pll_settings *pll_settings) ++{ ++ uint32_t err_tolerance; ++ uint32_t min_post_divider; ++ uint32_t max_post_divider; ++ uint32_t min_ref_divider; ++ uint32_t max_ref_divider; ++ ++ if (pll_settings->adjusted_pix_clk == 0) { ++ dal_logger_write(calc_pll_cs->ctx->logger, ++ LOG_MAJOR_ERROR, ++ LOG_MINOR_COMPONENT_GPU, ++ "%s Bad requested pixel clock", __func__); ++ return MAX_PLL_CALC_ERROR; ++ } ++ ++/* 1) Find Post divider ranges */ ++ if (pll_settings->pix_clk_post_divider) { ++ min_post_divider = pll_settings->pix_clk_post_divider; ++ max_post_divider = pll_settings->pix_clk_post_divider; ++ } else { ++ min_post_divider = calc_pll_cs->min_pix_clock_pll_post_divider; ++ if (min_post_divider * pll_settings->adjusted_pix_clk < ++ calc_pll_cs->min_vco_khz) { ++ min_post_divider = calc_pll_cs->min_vco_khz / ++ pll_settings->adjusted_pix_clk; ++ if ((min_post_divider * ++ pll_settings->adjusted_pix_clk) < ++ calc_pll_cs->min_vco_khz) ++ min_post_divider++; ++ } ++ ++ max_post_divider = calc_pll_cs->max_pix_clock_pll_post_divider; ++ if (max_post_divider * pll_settings->adjusted_pix_clk ++ > calc_pll_cs->max_vco_khz) ++ max_post_divider = calc_pll_cs->max_vco_khz / ++ pll_settings->adjusted_pix_clk; ++ } ++ ++/* 2) Find Reference divider ranges ++ * When SS is enabled, or for Display Port even without SS, ++ * pll_settings->referenceDivider is not zero. ++ * So calculate PPLL FB and fractional FB divider ++ * using the passed reference divider*/ ++ ++ if (pll_settings->reference_divider) { ++ min_ref_divider = pll_settings->reference_divider; ++ max_ref_divider = pll_settings->reference_divider; ++ } else { ++ min_ref_divider = ((calc_pll_cs->ref_freq_khz ++ / calc_pll_cs->max_pll_input_freq_khz) ++ > calc_pll_cs->min_pll_ref_divider) ++ ? calc_pll_cs->ref_freq_khz ++ / calc_pll_cs->max_pll_input_freq_khz ++ : calc_pll_cs->min_pll_ref_divider; ++ ++ max_ref_divider = ((calc_pll_cs->ref_freq_khz ++ / calc_pll_cs->min_pll_input_freq_khz) ++ < calc_pll_cs->max_pll_ref_divider) ++ ? calc_pll_cs->ref_freq_khz / ++ calc_pll_cs->min_pll_input_freq_khz ++ : calc_pll_cs->max_pll_ref_divider; ++ } ++ ++/* If some parameters are invalid we could have scenario when "min">"max" ++ * which produced endless loop later. ++ * We should investigate why we get the wrong parameters. ++ * But to follow the similar logic when "adjustedPixelClock" is set to be 0 ++ * it is better to return here than cause system hang/watchdog timeout later. ++ * ## SVS Wed 15 Jul 2009 */ ++ ++ if (min_post_divider > max_post_divider) { ++ dal_logger_write(calc_pll_cs->ctx->logger, ++ LOG_MAJOR_ERROR, ++ LOG_MINOR_COMPONENT_GPU, ++ "%s Post divider range is invalid", __func__); ++ return MAX_PLL_CALC_ERROR; ++ } ++ ++ if (min_ref_divider > max_ref_divider) { ++ dal_logger_write(calc_pll_cs->ctx->logger, ++ LOG_MAJOR_ERROR, ++ LOG_MINOR_COMPONENT_GPU, ++ "%s Reference divider range is invalid", __func__); ++ return MAX_PLL_CALC_ERROR; ++ } ++ ++/* 3) Try to find PLL dividers given ranges ++ * starting with minimal error tolerance. ++ * Increase error tolerance until PLL dividers found*/ ++ err_tolerance = MAX_PLL_CALC_ERROR; ++ ++ while (!calc_pll_dividers_in_range( ++ calc_pll_cs, ++ pll_settings, ++ min_ref_divider, ++ max_ref_divider, ++ min_post_divider, ++ max_post_divider, ++ err_tolerance)) ++ err_tolerance += (err_tolerance > 10) ++ ? (err_tolerance / 10) ++ : 1; ++ ++ return err_tolerance; ++} ++ ++static bool pll_adjust_pix_clk( ++ struct dce110_clk_src *clk_src, ++ struct pixel_clk_params *pix_clk_params, ++ struct pll_settings *pll_settings) ++{ ++ uint32_t actual_pix_clk_khz = 0; ++ uint32_t requested_clk_khz = 0; ++ struct bp_adjust_pixel_clock_parameters bp_adjust_pixel_clock_params = { ++ 0 }; ++ enum bp_result bp_result; ++ ++ switch (pix_clk_params->signal_type) { ++ case SIGNAL_TYPE_HDMI_TYPE_A: { ++ requested_clk_khz = pix_clk_params->requested_pix_clk; ++ ++ switch (pix_clk_params->color_depth) { ++ case COLOR_DEPTH_101010: ++ requested_clk_khz = (requested_clk_khz * 5) >> 2; ++ break; /* x1.25*/ ++ case COLOR_DEPTH_121212: ++ requested_clk_khz = (requested_clk_khz * 6) >> 2; ++ break; /* x1.5*/ ++ case COLOR_DEPTH_161616: ++ requested_clk_khz = requested_clk_khz * 2; ++ break; /* x2.0*/ ++ default: ++ break; ++ } ++ ++ actual_pix_clk_khz = requested_clk_khz; ++ } ++ break; ++ ++ case SIGNAL_TYPE_DISPLAY_PORT: ++ case SIGNAL_TYPE_DISPLAY_PORT_MST: ++ case SIGNAL_TYPE_EDP: ++ requested_clk_khz = pix_clk_params->requested_sym_clk; ++ actual_pix_clk_khz = pix_clk_params->requested_pix_clk; ++ break; ++ ++ default: ++ requested_clk_khz = pix_clk_params->requested_pix_clk; ++ actual_pix_clk_khz = pix_clk_params->requested_pix_clk; ++ break; ++ } ++ ++ bp_adjust_pixel_clock_params.pixel_clock = requested_clk_khz; ++ bp_adjust_pixel_clock_params. ++ encoder_object_id = pix_clk_params->encoder_object_id; ++ bp_adjust_pixel_clock_params.signal_type = pix_clk_params->signal_type; ++ bp_adjust_pixel_clock_params. ++ ss_enable = pix_clk_params->flags.ENABLE_SS; ++ bp_result = clk_src->bios->funcs->adjust_pixel_clock( ++ clk_src->bios, &bp_adjust_pixel_clock_params); ++ if (bp_result == BP_RESULT_OK) { ++ pll_settings->actual_pix_clk = actual_pix_clk_khz; ++ pll_settings->adjusted_pix_clk = ++ bp_adjust_pixel_clock_params.adjusted_pixel_clock; ++ pll_settings->reference_divider = ++ bp_adjust_pixel_clock_params.reference_divider; ++ pll_settings->pix_clk_post_divider = ++ bp_adjust_pixel_clock_params.pixel_clock_post_divider; ++ ++ return true; ++ } ++ ++ return false; ++} ++ ++/** ++ * Calculate PLL Dividers for given Clock Value. ++ * First will call VBIOS Adjust Exec table to check if requested Pixel clock ++ * will be Adjusted based on usage. ++ * Then it will calculate PLL Dividers for this Adjusted clock using preferred ++ * method (Maximum VCO frequency). ++ * ++ * \return ++ * Calculation error in units of 0.01% ++ */ ++static uint32_t dce110_get_pix_clk_dividers( ++ struct clock_source *cs, ++ struct pixel_clk_params *pix_clk_params, ++ struct pll_settings *pll_settings) ++{ ++ struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(cs); ++ uint32_t pll_calc_error = MAX_PLL_CALC_ERROR; ++ uint32_t addr = 0; ++ uint32_t value = 0; ++ uint32_t field = 0; ++ ++ if (pix_clk_params == NULL || pll_settings == NULL ++ || pix_clk_params->requested_pix_clk == 0) { ++ dal_logger_write(clk_src->base.ctx->logger, ++ LOG_MAJOR_ERROR, ++ LOG_MINOR_COMPONENT_GPU, ++ "%s: Invalid parameters!!\n", __func__); ++ return pll_calc_error; ++ } ++ ++ dc_service_memset(pll_settings, 0, sizeof(*pll_settings)); ++ ++ if (cs->id == CLOCK_SOURCE_ID_EXTERNAL) { ++ pll_settings->adjusted_pix_clk = clk_src->ext_clk_khz; ++ pll_settings->calculated_pix_clk = clk_src->ext_clk_khz; ++ pll_settings->actual_pix_clk = ++ pix_clk_params->requested_pix_clk; ++ return 0; ++ } ++ /* PLL only after this point */ ++ ++ /* Check if reference clock is external (not pcie/xtalin) ++ * HW Dce80 spec: ++ * 00 - PCIE_REFCLK, 01 - XTALIN, 02 - GENERICA, 03 - GENERICB ++ * 04 - HSYNCA, 05 - GENLK_CLK, 06 - PCIE_REFCLK, 07 - DVOCLK0 */ ++ addr = clk_src->offsets.pll_cntl; ++ value = dal_read_reg(clk_src->base.ctx, addr); ++ field = get_reg_field_value(value, PLL_CNTL, PLL_REF_DIV_SRC); ++ pll_settings->use_external_clk = (field > 1); ++ ++ /* VBIOS by default enables DP SS (spread on IDCLK) for DCE 8.0 always ++ * (we do not care any more from SI for some older DP Sink which ++ * does not report SS support, no known issues) */ ++ if ((pix_clk_params->flags.ENABLE_SS) || ++ (dc_is_dp_signal(pix_clk_params->signal_type))) { ++ ++ const struct spread_spectrum_data *ss_data = get_ss_data_entry( ++ clk_src, ++ pix_clk_params->signal_type, ++ pll_settings->adjusted_pix_clk); ++ ++ if (NULL != ss_data) ++ pll_settings->ss_percentage = ss_data->percentage; ++ } ++ ++ /* Check VBIOS AdjustPixelClock Exec table */ ++ if (!pll_adjust_pix_clk(clk_src, pix_clk_params, pll_settings)) { ++ /* Should never happen, ASSERT and fill up values to be able ++ * to continue. */ ++ dal_logger_write(clk_src->base.ctx->logger, ++ LOG_MAJOR_ERROR, ++ LOG_MINOR_COMPONENT_GPU, ++ "%s: Failed to adjust pixel clock!!", __func__); ++ pll_settings->actual_pix_clk = ++ pix_clk_params->requested_pix_clk; ++ pll_settings->adjusted_pix_clk = ++ pix_clk_params->requested_pix_clk; ++ ++ if (dc_is_dp_signal(pix_clk_params->signal_type)) ++ pll_settings->adjusted_pix_clk = 100000; ++ } ++ ++ /* Calculate Dividers */ ++ if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) ++ /*Calculate Dividers by HDMI object, no SS case or SS case */ ++ pll_calc_error = ++ calculate_pixel_clock_pll_dividers( ++ &clk_src->calc_pll_hdmi, ++ pll_settings); ++ else ++ /*Calculate Dividers by default object, no SS case or SS case */ ++ pll_calc_error = ++ calculate_pixel_clock_pll_dividers( ++ &clk_src->calc_pll, ++ pll_settings); ++ ++ return pll_calc_error; ++} ++ ++static bool disable_spread_spectrum(struct dce110_clk_src *clk_src) ++{ ++ enum bp_result result; ++ struct bp_spread_spectrum_parameters bp_ss_params = {0}; ++ ++ bp_ss_params.pll_id = clk_src->base.id; ++ ++ /*Call ASICControl to process ATOMBIOS Exec table*/ ++ result = clk_src->bios->funcs->enable_spread_spectrum_on_ppll( ++ clk_src->bios, ++ &bp_ss_params, ++ false); ++ ++ return result == BP_RESULT_OK; ++} ++ ++static bool calculate_ss( ++ const struct pll_settings *pll_settings, ++ const struct spread_spectrum_data *ss_data, ++ struct delta_sigma_data *ds_data) ++{ ++ struct fixed32_32 fb_div; ++ struct fixed32_32 ss_amount; ++ struct fixed32_32 ss_nslip_amount; ++ struct fixed32_32 ss_ds_frac_amount; ++ struct fixed32_32 ss_step_size; ++ struct fixed32_32 modulation_time; ++ ++ if (ds_data == NULL) ++ return false; ++ if (ss_data == NULL) ++ return false; ++ if (ss_data->percentage == 0) ++ return false; ++ if (pll_settings == NULL) ++ return false; ++ ++ ++ dc_service_memset(ds_data, 0, sizeof(struct delta_sigma_data)); ++ ++ ++ ++ /* compute SS_AMOUNT_FBDIV & SS_AMOUNT_NFRAC_SLIP & SS_AMOUNT_DSFRAC*/ ++ /* 6 decimal point support in fractional feedback divider */ ++ fb_div = dal_fixed32_32_from_fraction( ++ pll_settings->fract_feedback_divider, 1000000); ++ fb_div = dal_fixed32_32_add_int(fb_div, pll_settings->feedback_divider); ++ ++ ds_data->ds_frac_amount = 0; ++ /*spreadSpectrumPercentage is in the unit of .01%, ++ * so have to divided by 100 * 100*/ ++ ss_amount = dal_fixed32_32_mul( ++ fb_div, dal_fixed32_32_from_fraction(ss_data->percentage, ++ 100 * ss_data->percentage_divider)); ++ ds_data->feedback_amount = dal_fixed32_32_floor(ss_amount); ++ ++ ss_nslip_amount = dal_fixed32_32_sub(ss_amount, ++ dal_fixed32_32_from_int(ds_data->feedback_amount)); ++ ss_nslip_amount = dal_fixed32_32_mul_int(ss_nslip_amount, 10); ++ ds_data->nfrac_amount = dal_fixed32_32_floor(ss_nslip_amount); ++ ++ ss_ds_frac_amount = dal_fixed32_32_sub(ss_nslip_amount, ++ dal_fixed32_32_from_int(ds_data->nfrac_amount)); ++ ss_ds_frac_amount = dal_fixed32_32_mul_int(ss_ds_frac_amount, 65536); ++ ds_data->ds_frac_amount = dal_fixed32_32_floor(ss_ds_frac_amount); ++ ++ /* compute SS_STEP_SIZE_DSFRAC */ ++ modulation_time = dal_fixed32_32_from_fraction( ++ pll_settings->reference_freq * 1000, ++ pll_settings->reference_divider * ss_data->modulation_freq_hz); ++ ++ ++ if (ss_data->flags.CENTER_SPREAD) ++ modulation_time = dal_fixed32_32_div_int(modulation_time, 4); ++ else ++ modulation_time = dal_fixed32_32_div_int(modulation_time, 2); ++ ++ ss_step_size = dal_fixed32_32_div(ss_amount, modulation_time); ++ /* SS_STEP_SIZE_DSFRAC_DEC = Int(SS_STEP_SIZE * 2 ^ 16 * 10)*/ ++ ss_step_size = dal_fixed32_32_mul_int(ss_step_size, 65536 * 10); ++ ds_data->ds_frac_size = dal_fixed32_32_floor(ss_step_size); ++ ++ return true; ++} ++ ++static bool enable_spread_spectrum( ++ struct dce110_clk_src *clk_src, ++ enum signal_type signal, struct pll_settings *pll_settings) ++{ ++ struct bp_spread_spectrum_parameters bp_params = {0}; ++ struct delta_sigma_data d_s_data; ++ const struct spread_spectrum_data *ss_data = NULL; ++ ++ ss_data = get_ss_data_entry( ++ clk_src, ++ signal, ++ pll_settings->calculated_pix_clk); ++ ++/* Pixel clock PLL has been programmed to generate desired pixel clock, ++ * now enable SS on pixel clock */ ++/* TODO is it OK to return true not doing anything ??*/ ++ if (ss_data != NULL && pll_settings->ss_percentage != 0) { ++ if (calculate_ss(pll_settings, ss_data, &d_s_data)) { ++ bp_params.ds.feedback_amount = ++ d_s_data.feedback_amount; ++ bp_params.ds.nfrac_amount = ++ d_s_data.nfrac_amount; ++ bp_params.ds.ds_frac_size = d_s_data.ds_frac_size; ++ bp_params.ds_frac_amount = ++ d_s_data.ds_frac_amount; ++ bp_params.flags.DS_TYPE = 1; ++ bp_params.pll_id = clk_src->base.id; ++ bp_params.percentage = ss_data->percentage; ++ if (ss_data->flags.CENTER_SPREAD) ++ bp_params.flags.CENTER_SPREAD = 1; ++ if (ss_data->flags.EXTERNAL_SS) ++ bp_params.flags.EXTERNAL_SS = 1; ++ ++ if (BP_RESULT_OK != ++ clk_src->bios->funcs-> ++ enable_spread_spectrum_on_ppll( ++ clk_src->bios, ++ &bp_params, ++ true)) ++ return false; ++ } else ++ return false; ++ } ++ return true; ++} ++ ++static void program_pixel_clk_resync( ++ struct dce110_clk_src *clk_src, ++ enum signal_type signal_type, ++ enum dc_color_depth colordepth) ++{ ++ uint32_t value = 0; ++ ++ value = dal_read_reg(clk_src->base.ctx, clk_src->offsets.pixclk_resync_cntl); ++ ++ set_reg_field_value( ++ value, ++ 0, ++ PIXCLK1_RESYNC_CNTL, ++ DCCG_DEEP_COLOR_CNTL1); ++ ++ /* ++ 24 bit mode: TMDS clock = 1.0 x pixel clock (1:1) ++ 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4) ++ 36 bit mode: TMDS clock = 1.5 x pixel clock (3:2) ++ 48 bit mode: TMDS clock = 2 x pixel clock (2:1) ++ */ ++ if (signal_type != SIGNAL_TYPE_HDMI_TYPE_A) ++ return; ++ ++ switch (colordepth) { ++ case COLOR_DEPTH_888: ++ set_reg_field_value( ++ value, ++ 0, ++ PIXCLK1_RESYNC_CNTL, ++ DCCG_DEEP_COLOR_CNTL1); ++ break; ++ case COLOR_DEPTH_101010: ++ set_reg_field_value( ++ value, ++ 1, ++ PIXCLK1_RESYNC_CNTL, ++ DCCG_DEEP_COLOR_CNTL1); ++ break; ++ case COLOR_DEPTH_121212: ++ set_reg_field_value( ++ value, ++ 2, ++ PIXCLK1_RESYNC_CNTL, ++ DCCG_DEEP_COLOR_CNTL1); ++ break; ++ case COLOR_DEPTH_161616: ++ set_reg_field_value( ++ value, ++ 3, ++ PIXCLK1_RESYNC_CNTL, ++ DCCG_DEEP_COLOR_CNTL1); ++ break; ++ default: ++ break; ++ } ++ ++ dal_write_reg( ++ clk_src->base.ctx, ++ clk_src->offsets.pixclk_resync_cntl, ++ value); ++} ++ ++static bool dce110_program_pix_clk( ++ struct clock_source *clk_src, ++ struct pixel_clk_params *pix_clk_params, ++ struct pll_settings *pll_settings) ++{ ++ struct dce110_clk_src *dce110_clk_src = TO_DCE110_CLK_SRC(clk_src); ++ struct bp_pixel_clock_parameters bp_pc_params = {0}; ++ ++ /* First disable SS ++ * ATOMBIOS will enable by default SS on PLL for DP, ++ * do not disable it here ++ */ ++ if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL && ++ !dc_is_dp_signal(pix_clk_params->signal_type)) ++ disable_spread_spectrum(dce110_clk_src); ++ ++ /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/ ++ bp_pc_params.controller_id = pix_clk_params->controller_id; ++ bp_pc_params.pll_id = clk_src->id; ++ bp_pc_params.target_pixel_clock = ++ pll_settings->actual_pix_clk; ++ bp_pc_params.reference_divider = pll_settings->reference_divider; ++ bp_pc_params.feedback_divider = pll_settings->feedback_divider; ++ bp_pc_params.fractional_feedback_divider = ++ pll_settings->fract_feedback_divider; ++ bp_pc_params.pixel_clock_post_divider = ++ pll_settings->pix_clk_post_divider; ++ bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; ++ bp_pc_params.signal_type = pix_clk_params->signal_type; ++ bp_pc_params.flags.SET_EXTERNAL_REF_DIV_SRC = ++ pll_settings->use_external_clk; ++ ++ if (dce110_clk_src->bios->funcs->set_pixel_clock( ++ dce110_clk_src->bios, &bp_pc_params) != BP_RESULT_OK) ++ return false; ++ ++/* Enable SS ++ * ATOMBIOS will enable by default SS for DP on PLL ( DP ID clock), ++ * based on HW display PLL team, SS control settings should be programmed ++ * during PLL Reset, but they do not have effect ++ * until SS_EN is asserted.*/ ++ if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL ++ && pix_clk_params->flags.ENABLE_SS && !dc_is_dp_signal( ++ pix_clk_params->signal_type)) ++ if (!enable_spread_spectrum(dce110_clk_src, ++ pix_clk_params->signal_type, ++ pll_settings)) ++ return false; ++ ++/* Resync deep color DTO */ ++ if (clk_src->id != CLOCK_SOURCE_ID_EXTERNAL) ++ program_pixel_clk_resync(dce110_clk_src, ++ pix_clk_params->signal_type, ++ pix_clk_params->color_depth); ++ ++ return true; ++} ++ ++static bool dce110_clock_source_power_down( ++ struct clock_source *clk_src, enum controller_id controller_id) ++{ ++ struct dce110_clk_src *dce110_clk_src = TO_DCE110_CLK_SRC(clk_src); ++ enum bp_result bp_result; ++ struct bp_pixel_clock_parameters bp_pixel_clock_params = {0}; ++ ++ if (clk_src->id == CLOCK_SOURCE_ID_EXTERNAL) ++ return true; ++ ++ /* If Pixel Clock is 0 it means Power Down Pll*/ ++ bp_pixel_clock_params.controller_id = controller_id; ++ bp_pixel_clock_params.pll_id = clk_src->id; ++ bp_pixel_clock_params.flags.FORCE_PROGRAMMING_OF_PLL = 1; ++ ++ /*Call ASICControl to process ATOMBIOS Exec table*/ ++ bp_result = dce110_clk_src->bios->funcs->set_pixel_clock( ++ dce110_clk_src->bios, ++ &bp_pixel_clock_params); ++ ++ return bp_result == BP_RESULT_OK; ++} ++ ++ ++/*****************************************/ ++/* Constructor */ ++/*****************************************/ ++static struct clock_source_funcs dce110_clk_src_funcs = { ++ .cs_power_down = dce110_clock_source_power_down, ++ .program_pix_clk = dce110_program_pix_clk, ++ .get_pix_clk_dividers = dce110_get_pix_clk_dividers ++}; ++ ++ ++static void get_ss_info_from_atombios( ++ struct dce110_clk_src *clk_src, ++ enum as_signal_type as_signal, ++ struct spread_spectrum_data *spread_spectrum_data[], ++ uint32_t *ss_entries_num) ++{ ++ enum bp_result bp_result = BP_RESULT_FAILURE; ++ struct spread_spectrum_info *ss_info; ++ struct spread_spectrum_data *ss_data; ++ struct spread_spectrum_info *ss_info_cur; ++ struct spread_spectrum_data *ss_data_cur; ++ uint32_t i; ++ ++ if (ss_entries_num == NULL) { ++ dal_logger_write(clk_src->base.ctx->logger, ++ LOG_MAJOR_SYNC, ++ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, ++ "Invalid entry !!!\n"); ++ return; ++ } ++ if (spread_spectrum_data == NULL) { ++ dal_logger_write(clk_src->base.ctx->logger, ++ LOG_MAJOR_SYNC, ++ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, ++ "Invalid array pointer!!!\n"); ++ return; ++ } ++ ++ spread_spectrum_data[0] = NULL; ++ *ss_entries_num = 0; ++ ++ *ss_entries_num = clk_src->bios->funcs->get_ss_entry_number( ++ clk_src->bios, ++ as_signal); ++ ++ if (*ss_entries_num == 0) ++ return; ++ ++ ss_info = dc_service_alloc(clk_src->base.ctx, sizeof(struct spread_spectrum_info) ++ * (*ss_entries_num)); ++ ss_info_cur = ss_info; ++ if (ss_info == NULL) ++ return; ++ ++ ss_data = dc_service_alloc(clk_src->base.ctx, sizeof(struct spread_spectrum_data) * ++ (*ss_entries_num)); ++ if (ss_data == NULL) ++ goto out_free_info; ++ ++ for (i = 0, ss_info_cur = ss_info; ++ i < (*ss_entries_num); ++ ++i, ++ss_info_cur) { ++ ++ bp_result = clk_src->bios->funcs->get_spread_spectrum_info( ++ clk_src->bios, ++ as_signal, ++ i, ++ ss_info_cur); ++ ++ if (bp_result != BP_RESULT_OK) ++ goto out_free_data; ++ } ++ ++ for (i = 0, ss_info_cur = ss_info, ss_data_cur = ss_data; ++ i < (*ss_entries_num); ++ ++i, ++ss_info_cur, ++ss_data_cur) { ++ ++ if (ss_info_cur->type.STEP_AND_DELAY_INFO != false) { ++ dal_logger_write(clk_src->base.ctx->logger, ++ LOG_MAJOR_SYNC, ++ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, ++ "Invalid ATOMBIOS SS Table!!!\n"); ++ goto out_free_data; ++ } ++ ++ /* for HDMI check SS percentage, ++ * if it is > 6 (0.06%), the ATOMBIOS table info is invalid*/ ++ if (as_signal == AS_SIGNAL_TYPE_HDMI ++ && ss_info_cur->spread_spectrum_percentage > 6){ ++ /* invalid input, do nothing */ ++ dal_logger_write(clk_src->base.ctx->logger, ++ LOG_MAJOR_SYNC, ++ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, ++ "Invalid SS percentage "); ++ dal_logger_write(clk_src->base.ctx->logger, ++ LOG_MAJOR_SYNC, ++ LOG_MINOR_SYNC_HW_CLOCK_ADJUST, ++ "for HDMI in ATOMBIOS info Table!!!\n"); ++ continue; ++ } ++ if (ss_info_cur->spread_percentage_divider == 1000) { ++ /* Keep previous precision from ATOMBIOS for these ++ * in case new precision set by ATOMBIOS for these ++ * (otherwise all code in DCE specific classes ++ * for all previous ASICs would need ++ * to be updated for SS calculations, ++ * Audio SS compensation and DP DTO SS compensation ++ * which assumes fixed SS percentage Divider = 100)*/ ++ ss_info_cur->spread_spectrum_percentage /= 10; ++ ss_info_cur->spread_percentage_divider = 100; ++ } ++ ++ ss_data_cur->freq_range_khz = ss_info_cur->target_clock_range; ++ ss_data_cur->percentage = ++ ss_info_cur->spread_spectrum_percentage; ++ ss_data_cur->percentage_divider = ++ ss_info_cur->spread_percentage_divider; ++ ss_data_cur->modulation_freq_hz = ++ ss_info_cur->spread_spectrum_range; ++ ++ if (ss_info_cur->type.CENTER_MODE) ++ ss_data_cur->flags.CENTER_SPREAD = 1; ++ ++ if (ss_info_cur->type.EXTERNAL) ++ ss_data_cur->flags.EXTERNAL_SS = 1; ++ ++ } ++ ++ *spread_spectrum_data = ss_data; ++ dc_service_free(clk_src->base.ctx, ss_info); ++ return; ++ ++out_free_data: ++ dc_service_free(clk_src->base.ctx, ss_data); ++ *ss_entries_num = 0; ++out_free_info: ++ dc_service_free(clk_src->base.ctx, ss_info); ++} ++ ++static void ss_info_from_atombios_create( ++ struct dce110_clk_src *clk_src) ++{ ++ get_ss_info_from_atombios( ++ clk_src, ++ AS_SIGNAL_TYPE_DISPLAY_PORT, ++ &clk_src->dp_ss_params, ++ &clk_src->dp_ss_params_cnt); ++ get_ss_info_from_atombios( ++ clk_src, ++ AS_SIGNAL_TYPE_HDMI, ++ &clk_src->hdmi_ss_params, ++ &clk_src->hdmi_ss_params_cnt); ++ get_ss_info_from_atombios( ++ clk_src, ++ AS_SIGNAL_TYPE_DVI, ++ &clk_src->dvi_ss_params, ++ &clk_src->dvi_ss_params_cnt); ++} ++ ++static bool calc_pll_max_vco_construct( ++ struct calc_pll_clock_source *calc_pll_cs, ++ struct calc_pll_clock_source_init_data *init_data) ++{ ++ uint32_t i; ++ struct firmware_info fw_info = { { 0 } }; ++ if (calc_pll_cs == NULL || ++ init_data == NULL || ++ init_data->bp == NULL) ++ return false; ++ ++ if (init_data->bp->funcs->get_firmware_info( ++ init_data->bp, ++ &fw_info) != BP_RESULT_OK) ++ return false; ++ ++ calc_pll_cs->ctx = init_data->ctx; ++ calc_pll_cs->ref_freq_khz = fw_info.pll_info.crystal_frequency; ++ calc_pll_cs->min_vco_khz = ++ fw_info.pll_info.min_output_pxl_clk_pll_frequency; ++ calc_pll_cs->max_vco_khz = ++ fw_info.pll_info.max_output_pxl_clk_pll_frequency; ++ ++ if (init_data->max_override_input_pxl_clk_pll_freq_khz != 0) ++ calc_pll_cs->max_pll_input_freq_khz = ++ init_data->max_override_input_pxl_clk_pll_freq_khz; ++ else ++ calc_pll_cs->max_pll_input_freq_khz = ++ fw_info.pll_info.max_input_pxl_clk_pll_frequency; ++ ++ if (init_data->min_override_input_pxl_clk_pll_freq_khz != 0) ++ calc_pll_cs->min_pll_input_freq_khz = ++ init_data->min_override_input_pxl_clk_pll_freq_khz; ++ else ++ calc_pll_cs->min_pll_input_freq_khz = ++ fw_info.pll_info.min_input_pxl_clk_pll_frequency; ++ ++ calc_pll_cs->min_pix_clock_pll_post_divider = ++ init_data->min_pix_clk_pll_post_divider; ++ calc_pll_cs->max_pix_clock_pll_post_divider = ++ init_data->max_pix_clk_pll_post_divider; ++ calc_pll_cs->min_pll_ref_divider = ++ init_data->min_pll_ref_divider; ++ calc_pll_cs->max_pll_ref_divider = ++ init_data->max_pll_ref_divider; ++ ++ if (init_data->num_fract_fb_divider_decimal_point == 0 || ++ init_data->num_fract_fb_divider_decimal_point_precision > ++ init_data->num_fract_fb_divider_decimal_point) { ++ dal_logger_write(calc_pll_cs->ctx->logger, ++ LOG_MAJOR_ERROR, ++ LOG_MINOR_COMPONENT_GPU, ++ "The dec point num or precision is incorrect!"); ++ return false; ++ } ++ if (init_data->num_fract_fb_divider_decimal_point_precision == 0) { ++ dal_logger_write(calc_pll_cs->ctx->logger, ++ LOG_MAJOR_ERROR, ++ LOG_MINOR_COMPONENT_GPU, ++ "Incorrect fract feedback divider precision num!"); ++ return false; ++ } ++ ++ calc_pll_cs->fract_fb_divider_decimal_points_num = ++ init_data->num_fract_fb_divider_decimal_point; ++ calc_pll_cs->fract_fb_divider_precision = ++ init_data->num_fract_fb_divider_decimal_point_precision; ++ calc_pll_cs->fract_fb_divider_factor = 1; ++ for (i = 0; i < calc_pll_cs->fract_fb_divider_decimal_points_num; ++i) ++ calc_pll_cs->fract_fb_divider_factor *= 10; ++ ++ calc_pll_cs->fract_fb_divider_precision_factor = 1; ++ for ( ++ i = 0; ++ i < (calc_pll_cs->fract_fb_divider_decimal_points_num - ++ calc_pll_cs->fract_fb_divider_precision); ++ ++i) ++ calc_pll_cs->fract_fb_divider_precision_factor *= 10; ++ ++ return true; ++} ++ ++bool dce110_clk_src_construct( ++ struct dce110_clk_src *clk_src, ++ struct dc_context *ctx, ++ struct dc_bios *bios, ++ enum clock_source_id id, ++ const struct dce110_clk_src_reg_offsets *reg_offsets) ++{ ++ struct firmware_info fw_info = { { 0 } }; ++/* structure normally used with PLL ranges from ATOMBIOS; DS on by default */ ++ struct calc_pll_clock_source_init_data calc_pll_cs_init_data = { ++ bios, ++ 1, /* minPixelClockPLLPostDivider */ ++ PLL_POST_DIV__PLL_POST_DIV_PIXCLK_MASK, ++ /* maxPixelClockPLLPostDivider*/ ++ 1,/* minPLLRefDivider*/ ++ PLL_REF_DIV__PLL_REF_DIV_MASK,/* maxPLLRefDivider*/ ++ 0, ++/* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ ++ 0, ++/* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ ++ FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM, ++/*numberOfFractFBDividerDecimalPoints*/ ++ FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM, ++/*number of decimal point to round off for fractional feedback divider value*/ ++ ctx ++ }; ++/*structure for HDMI, no SS or SS% <= 0.06% for 27 MHz Ref clock */ ++ struct calc_pll_clock_source_init_data calc_pll_cs_init_data_hdmi = { ++ bios, ++ 1, /* minPixelClockPLLPostDivider */ ++ PLL_POST_DIV__PLL_POST_DIV_PIXCLK_MASK, ++ /* maxPixelClockPLLPostDivider*/ ++ 1,/* minPLLRefDivider*/ ++ PLL_REF_DIV__PLL_REF_DIV_MASK,/* maxPLLRefDivider*/ ++ 13500, ++ /* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ ++ 27000, ++ /* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ ++ FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM, ++ /*numberOfFractFBDividerDecimalPoints*/ ++ FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM, ++/*number of decimal point to round off for fractional feedback divider value*/ ++ ctx ++ }; ++ ++ clk_src->base.ctx = ctx; ++ clk_src->bios = bios; ++ clk_src->base.id = id; ++ clk_src->base.funcs = &dce110_clk_src_funcs; ++ clk_src->offsets = *reg_offsets; ++ ++ if (clk_src->bios->funcs->get_firmware_info( ++ clk_src->bios, &fw_info) != BP_RESULT_OK) { ++ ASSERT_CRITICAL(false); ++ goto unexpected_failure; ++ } ++ ++ clk_src->ext_clk_khz = ++ fw_info.external_clock_source_frequency_for_dp; ++ clk_src->ref_freq_khz = fw_info.pll_info.crystal_frequency; ++ ++ if (clk_src->base.id == CLOCK_SOURCE_ID_EXTERNAL) ++ return true; ++ ++ /* PLL only from here on */ ++ ss_info_from_atombios_create(clk_src); ++ ++ if (!calc_pll_max_vco_construct( ++ &clk_src->calc_pll, ++ &calc_pll_cs_init_data)) { ++ ASSERT_CRITICAL(false); ++ goto unexpected_failure; ++ } ++ ++ if (clk_src->ref_freq_khz == 48000) { ++ calc_pll_cs_init_data_hdmi. ++ min_override_input_pxl_clk_pll_freq_khz = 24000; ++ calc_pll_cs_init_data_hdmi. ++ max_override_input_pxl_clk_pll_freq_khz = 48000; ++ } else if (clk_src->ref_freq_khz == 100000) { ++ calc_pll_cs_init_data_hdmi. ++ min_override_input_pxl_clk_pll_freq_khz = 25000; ++ calc_pll_cs_init_data_hdmi. ++ max_override_input_pxl_clk_pll_freq_khz = 50000; ++ } ++ ++ if (!calc_pll_max_vco_construct( ++ &clk_src->calc_pll_hdmi, &calc_pll_cs_init_data_hdmi)) { ++ ASSERT_CRITICAL(false); ++ goto unexpected_failure; ++ } ++ ++ return true; ++ ++unexpected_failure: ++ return false; ++} ++ ++ +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h +new file mode 100644 +index 0000000..4fa82da +--- /dev/null ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_clock_source.h +@@ -0,0 +1,64 @@ ++/* Copyright 2012-15 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 __DC_CLOCK_SOURCE_DCE110_H__ ++#define __DC_CLOCK_SOURCE_DCE110_H__ ++ ++#include "../inc/clock_source.h" ++ ++#define TO_DCE110_CLK_SRC(clk_src)\ ++ container_of(clk_src, struct dce110_clk_src, base) ++ ++struct dce110_clk_src_reg_offsets { ++ uint32_t pll_cntl; ++ uint32_t pixclk_resync_cntl; ++}; ++ ++struct dce110_clk_src { ++ struct clock_source base; ++ struct dce110_clk_src_reg_offsets offsets; ++ struct dc_bios *bios; ++ ++ struct spread_spectrum_data *dp_ss_params; ++ uint32_t dp_ss_params_cnt; ++ struct spread_spectrum_data *hdmi_ss_params; ++ uint32_t hdmi_ss_params_cnt; ++ struct spread_spectrum_data *dvi_ss_params; ++ uint32_t dvi_ss_params_cnt; ++ ++ uint32_t ext_clk_khz; ++ uint32_t ref_freq_khz; ++ ++ struct calc_pll_clock_source calc_pll; ++ struct calc_pll_clock_source calc_pll_hdmi; ++}; ++ ++bool dce110_clk_src_construct( ++ struct dce110_clk_src *clk_src, ++ struct dc_context *ctx, ++ struct dc_bios *bios, ++ enum clock_source_id, ++ const struct dce110_clk_src_reg_offsets *reg_offsets); ++ ++#endif +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c +index e716219..af7cf0d 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_hw_sequencer.c +@@ -33,13 +33,14 @@ + + #include "dce110/dce110_resource.h" + #include "dce110/dce110_timing_generator.h" +-#include "dce110/dce110_link_encoder.h" +-#include "dce110/dce110_stream_encoder.h" + #include "dce110/dce110_mem_input.h" +-#include "dce110/dce110_ipp.h" +-#include "dce110/dce110_transform.h" + #include "dce110/dce110_opp.h" + #include "gpu/dce110/dc_clock_gating_dce110.h" ++#include "ipp.h" ++#include "transform.h" ++#include "stream_encoder.h" ++#include "link_encoder.h" ++#include "inc/clock_source.h" + + /* include DCE11 register header files */ + #include "dce/dce_11_0_d.h" +@@ -806,7 +807,7 @@ static enum dc_status apply_single_controller_ctx_to_hw(uint8_t controller_idx, + core_link_disable_stream(stream->sink->link, stream); + + /*TODO: AUTO check if timing changed*/ +- if (false == dal_clock_source_program_pix_clk( ++ if (false == stream->clock_source->funcs->program_pix_clk( + stream->clock_source, + &stream->pix_clk_params, + &stream->pll_settings)) { +@@ -932,13 +933,9 @@ static void power_down_clock_sources(struct dc *dc) + int i; + + for (i = 0; i < dc->res_pool.clk_src_count; i++) { +- if (false == dal_clock_source_power_down_pll( +- dc->res_pool.clock_sources[i], +- i+1)) { +- dal_error( +- "Failed to power down pll! (clk src index=%d)\n", +- i); +- } ++ if (dc->res_pool.clock_sources[i]->funcs->cs_power_down( ++ dc->res_pool.clock_sources[i], i+1) == false) ++ dal_error("Failed to power down pll! (clk src index=%d)\n", i); + } + } + +@@ -1200,7 +1197,7 @@ static void dce110_switch_dp_clk_src( + { + uint32_t pixel_rate_cntl_value; + uint32_t addr; +- enum clock_source_id id = dal_clock_source_get_id(stream->clock_source); ++ enum clock_source_id id = stream->clock_source->id; + + /*TODO: proper offset*/ + addr = mmCRTC0_PIXEL_RATE_CNTL + stream->controller_idx * +@@ -1761,7 +1758,6 @@ static const struct hw_sequencer_funcs dce110_funcs = { + .encoder_create = dce110_link_encoder_create, + .encoder_destroy = dce110_link_encoder_destroy, + .clock_gating_power_up = dal_dc_clock_gating_dce110_power_up, +- .transform_power_up = dce110_transform_power_up, + .construct_resource_pool = dce110_construct_resource_pool, + .destruct_resource_pool = dce110_destruct_resource_pool, + .validate_with_context = dce110_validate_with_context, +diff --git a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c +index bd9f311..41717eb 100644 +--- a/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c ++++ b/drivers/gpu/drm/amd/dal/dc/dce110/dce110_resource.c +@@ -39,6 +39,7 @@ + #include "dce110/dce110_transform.h" + #include "dce110/dce110_stream_encoder.h" + #include "dce110/dce110_opp.h" ++#include "dce110/dce110_clock_source.h" + + #include "dce/dce_11_0_d.h" + +@@ -283,6 +284,17 @@ static const struct dce110_opp_reg_offsets dce110_opp_reg_offsets[] = { + }; + + ++static const struct dce110_clk_src_reg_offsets dce110_clk_src_reg_offsets[] = { ++ { ++ .pll_cntl = mmBPHYC_PLL0_PLL_CNTL, ++ .pixclk_resync_cntl = mmPIXCLK0_RESYNC_CNTL ++ }, ++ { ++ .pll_cntl = mmBPHYC_PLL1_PLL_CNTL, ++ .pixclk_resync_cntl = mmPIXCLK1_RESYNC_CNTL ++ } ++}; ++ + static struct timing_generator *dce110_timing_generator_create( + struct adapter_service *as, + struct dc_context *ctx, +@@ -438,6 +450,31 @@ static struct output_pixel_processor *dce110_opp_create( + return NULL; + } + ++struct clock_source *dce110_clock_source_create( ++ struct dc_context *ctx, ++ struct dc_bios *bios, ++ enum clock_source_id id, ++ const struct dce110_clk_src_reg_offsets *offsets) ++{ ++ struct dce110_clk_src *clk_src = ++ dc_service_alloc(ctx, sizeof(struct dce110_clk_src)); ++ ++ if (!clk_src) ++ return NULL; ++ ++ if (dce110_clk_src_construct(clk_src, ctx, bios, id, offsets)) ++ return &clk_src->base; ++ ++ BREAK_TO_DEBUGGER(); ++ return NULL; ++} ++ ++void dce110_clock_source_destroy(struct clock_source **clk_src) ++{ ++ dc_service_free((*clk_src)->ctx, TO_DCE110_CLK_SRC(*clk_src)); ++ *clk_src = NULL; ++} ++ + bool dce110_construct_resource_pool( + struct adapter_service *adapter_serv, + uint8_t num_virtual_links, +@@ -445,7 +482,6 @@ bool dce110_construct_resource_pool( + struct resource_pool *pool) + { + unsigned int i; +- struct clock_source_init_data clk_src_init_data = { 0 }; + struct audio_init_data audio_init_data = { 0 }; + struct dc_context *ctx = dc->ctx; + pool->adapter_srv = adapter_serv; +@@ -457,22 +493,17 @@ bool dce110_construct_resource_pool( + pool->stream_engines.engine.ENGINE_ID_DIGE = 1; + pool->stream_engines.engine.ENGINE_ID_DIGF = 1; + +- clk_src_init_data.as = adapter_serv; +- clk_src_init_data.ctx = ctx; +- clk_src_init_data.clk_src_id.enum_id = ENUM_ID_1; +- clk_src_init_data.clk_src_id.type = OBJECT_TYPE_CLOCK_SOURCE; ++ pool->clock_sources[DCE110_CLK_SRC_PLL0] = dce110_clock_source_create( ++ ctx, dal_adapter_service_get_bios_parser(adapter_serv), ++ CLOCK_SOURCE_ID_PLL0, &dce110_clk_src_reg_offsets[0]); ++ pool->clock_sources[DCE110_CLK_SRC_PLL1] = dce110_clock_source_create( ++ ctx, dal_adapter_service_get_bios_parser(adapter_serv), ++ CLOCK_SOURCE_ID_PLL1, &dce110_clk_src_reg_offsets[1]); ++ pool->clock_sources[DCE110_CLK_SRC_EXT] = dce110_clock_source_create( ++ ctx, dal_adapter_service_get_bios_parser(adapter_serv), ++ CLOCK_SOURCE_ID_EXTERNAL, &dce110_clk_src_reg_offsets[0]); + pool->clk_src_count = DCE110_CLK_SRC_TOTAL; + +- clk_src_init_data.clk_src_id.id = CLOCK_SOURCE_ID_PLL0; +- pool->clock_sources[DCE110_CLK_SRC_PLL0] = dal_clock_source_create( +- &clk_src_init_data); +- clk_src_init_data.clk_src_id.id = CLOCK_SOURCE_ID_PLL1; +- pool->clock_sources[DCE110_CLK_SRC_PLL1] = dal_clock_source_create( +- &clk_src_init_data); +- clk_src_init_data.clk_src_id.id = CLOCK_SOURCE_ID_EXTERNAL; +- pool->clock_sources[DCE110_CLK_SRC_EXT] = dal_clock_source_create( +- &clk_src_init_data); +- + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] == NULL) { + dal_error("DC: failed to create clock sources!\n"); +@@ -658,7 +689,7 @@ disp_clk_create_fail: + clk_src_create_fail: + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] != NULL) +- dal_clock_source_destroy(&pool->clock_sources[i]); ++ dce110_clock_source_destroy(&pool->clock_sources[i]); + } + return false; + } +@@ -697,7 +728,7 @@ void dce110_destruct_resource_pool(struct resource_pool *pool) + + for (i = 0; i < pool->clk_src_count; i++) { + if (pool->clock_sources[i] != NULL) { +- dal_clock_source_destroy(&pool->clock_sources[i]); ++ dce110_clock_source_destroy(&pool->clock_sources[i]); + } + } + +@@ -846,7 +877,7 @@ static enum dc_status build_stream_hw_param(struct core_stream *stream) + stream->max_hdmi_pixel_clock = 600000; + + get_pixel_clock_parameters(stream, &stream->pix_clk_params); +- dal_clock_source_get_pix_clk_dividers( ++ stream->clock_source->funcs->get_pix_clk_dividers( + stream->clock_source, + &stream->pix_clk_params, + &stream->pll_settings); +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/Makefile b/drivers/gpu/drm/amd/dal/dc/gpu/Makefile +index d3d6faf..b481a6d 100644 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/Makefile ++++ b/drivers/gpu/drm/amd/dal/dc/gpu/Makefile +@@ -3,9 +3,7 @@ + # It provides the control and status of HW adapter resources, + # that are global for the ASIC and sharable between pipes. + +-GPU = calc_pll_clock_source.o clock_source.o \ +-dc_clock_generator.o display_clock.o divider_range.o \ +-ext_clock_source.o pll_clock_source.o ++GPU = dc_clock_generator.o display_clock.o divider_range.o + + AMD_DAL_GPU = $(addprefix $(AMDDALPATH)/dc/gpu/,$(GPU)) + +@@ -16,9 +14,7 @@ AMD_DAL_FILES += $(AMD_DAL_GPU) + # DCE 110 family + ############################################################################### + ifdef CONFIG_DRM_AMD_DAL_DCE11_0 +-GPU_DCE110 = display_clock_dce110.o \ +- pll_clock_source_dce110.o ext_clock_source_dce110.o \ +- vce_clock_source_dce110.o dc_clock_gating_dce110.o ++GPU_DCE110 = display_clock_dce110.o dc_clock_gating_dce110.o + + AMD_DAL_GPU_DCE110 = $(addprefix $(AMDDALPATH)/dc/gpu/dce110/,$(GPU_DCE110)) + +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.c b/drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.c +deleted file mode 100644 +index 4947d73..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.c ++++ /dev/null +@@ -1,407 +0,0 @@ +-/* Copyright 2012-15 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 "dc_services.h" +- +-#include "calc_pll_clock_source.h" +-#include "include/bios_parser_interface.h" +-#include "include/logger_interface.h" +- +-/** +-* Function: calculate_fb_and_fractional_fb_divider +-* +-* * DESCRIPTION: Calculates feedback and fractional feedback dividers values +-* +-*PARAMETERS: +-* targetPixelClock Desired frequency in 10 KHz +-* ref_divider Reference divider (already known) +-* postDivider Post Divider (already known) +-* feedback_divider_param Pointer where to store +-* calculated feedback divider value +-* fract_feedback_divider_param Pointer where to store +-* calculated fract feedback divider value +-* +-*RETURNS: +-* It fills the locations pointed by feedback_divider_param +-* and fract_feedback_divider_param +-* It returns - true if feedback divider not 0 +-* - false should never happen) +-*/ +-static bool calculate_fb_and_fractional_fb_divider( +- struct calc_pll_clock_source *calc_pll_cs, +- uint32_t target_pix_clk_khz, +- uint32_t ref_divider, +- uint32_t post_divider, +- uint32_t *feedback_divider_param, +- uint32_t *fract_feedback_divider_param) +-{ +- uint64_t feedback_divider; +- +- feedback_divider = +- (uint64_t)(target_pix_clk_khz * ref_divider * post_divider); +- feedback_divider *= 10; +- /* additional factor, since we divide by 10 afterwards */ +- feedback_divider *= (uint64_t)(calc_pll_cs->fract_fb_divider_factor); +- feedback_divider = div_u64(feedback_divider, calc_pll_cs->ref_freq_khz); +- +-/*Round to the number of precision +- * The following code replace the old code (ullfeedbackDivider + 5)/10 +- * for example if the difference between the number +- * of fractional feedback decimal point and the fractional FB Divider precision +- * is 2 then the equation becomes (ullfeedbackDivider + 5*100) / (10*100))*/ +- +- feedback_divider += (uint64_t) +- (5 * calc_pll_cs->fract_fb_divider_precision_factor); +- feedback_divider = +- div_u64(feedback_divider, +- calc_pll_cs->fract_fb_divider_precision_factor * 10); +- feedback_divider *= (uint64_t) +- (calc_pll_cs->fract_fb_divider_precision_factor); +- +- *feedback_divider_param = +- div_u64_rem( +- feedback_divider, +- calc_pll_cs->fract_fb_divider_factor, +- fract_feedback_divider_param); +- +- if (*feedback_divider_param != 0) +- return true; +- return false; +-} +- +-/** +-*calc_fb_divider_checking_tolerance +-* +-*DESCRIPTION: Calculates Feedback and Fractional Feedback divider values +-* for passed Reference and Post divider, checking for tolerance. +-*PARAMETERS: +-* pll_settings Pointer to structure +-* ref_divider Reference divider (already known) +-* postDivider Post Divider (already known) +-* tolerance Tolerance for Calculated Pixel Clock to be within +-* +-*RETURNS: +-* It fills the PLLSettings structure with PLL Dividers values +-* if calculated values are within required tolerance +-* It returns - true if eror is within tolerance +-* - false if eror is not within tolerance +-*/ +-static bool calc_fb_divider_checking_tolerance( +- struct calc_pll_clock_source *calc_pll_cs, +- struct pll_settings *pll_settings, +- uint32_t ref_divider, +- uint32_t post_divider, +- uint32_t tolerance) +-{ +- uint32_t feedback_divider; +- uint32_t fract_feedback_divider; +- uint32_t actual_calculated_clock_khz; +- uint32_t abs_err; +- uint64_t actual_calc_clk_khz; +- +- calculate_fb_and_fractional_fb_divider( +- calc_pll_cs, +- pll_settings->adjusted_pix_clk, +- ref_divider, +- post_divider, +- &feedback_divider, +- &fract_feedback_divider); +- +- /*Actual calculated value*/ +- actual_calc_clk_khz = (uint64_t)(feedback_divider * +- calc_pll_cs->fract_fb_divider_factor) + +- fract_feedback_divider; +- actual_calc_clk_khz *= calc_pll_cs->ref_freq_khz; +- actual_calc_clk_khz = +- div_u64(actual_calc_clk_khz, +- ref_divider * post_divider * +- calc_pll_cs->fract_fb_divider_factor); +- +- actual_calculated_clock_khz = (uint32_t)(actual_calc_clk_khz); +- +- abs_err = (actual_calculated_clock_khz > +- pll_settings->adjusted_pix_clk) +- ? actual_calculated_clock_khz - +- pll_settings->adjusted_pix_clk +- : pll_settings->adjusted_pix_clk - +- actual_calculated_clock_khz; +- +- if (abs_err <= tolerance) { +- /*found good values*/ +- pll_settings->reference_freq = calc_pll_cs->ref_freq_khz; +- pll_settings->reference_divider = ref_divider; +- pll_settings->feedback_divider = feedback_divider; +- pll_settings->fract_feedback_divider = fract_feedback_divider; +- pll_settings->pix_clk_post_divider = post_divider; +- pll_settings->calculated_pix_clk = +- actual_calculated_clock_khz; +- pll_settings->vco_freq = +- actual_calculated_clock_khz * post_divider; +- return true; +- } +- return false; +-} +- +-static bool calc_pll_dividers_in_range( +- struct calc_pll_clock_source *calc_pll_cs, +- struct pll_settings *pll_settings, +- uint32_t min_ref_divider, +- uint32_t max_ref_divider, +- uint32_t min_post_divider, +- uint32_t max_post_divider, +- uint32_t err_tolerance) +-{ +- uint32_t ref_divider; +- uint32_t post_divider; +- uint32_t tolerance; +- +-/* This is err_tolerance / 10000 = 0.0025 - acceptable error of 0.25% +- * This is errorTolerance / 10000 = 0.0001 - acceptable error of 0.01%*/ +- tolerance = (pll_settings->adjusted_pix_clk * err_tolerance) / +- 10000; +- if (tolerance < CALC_PLL_CLK_SRC_ERR_TOLERANCE) +- tolerance = CALC_PLL_CLK_SRC_ERR_TOLERANCE; +- +- for ( +- post_divider = max_post_divider; +- post_divider >= min_post_divider; +- --post_divider) { +- for ( +- ref_divider = min_ref_divider; +- ref_divider <= max_ref_divider; +- ++ref_divider) { +- if (calc_fb_divider_checking_tolerance( +- calc_pll_cs, +- pll_settings, +- ref_divider, +- post_divider, +- tolerance)) { +- return true; +- } +- } +- } +- +- return false; +-} +- +-uint32_t dal_clock_source_calculate_pixel_clock_pll_dividers( +- struct calc_pll_clock_source *calc_pll_cs, +- struct pll_settings *pll_settings) +-{ +- uint32_t err_tolerance; +- uint32_t min_post_divider; +- uint32_t max_post_divider; +- uint32_t min_ref_divider; +- uint32_t max_ref_divider; +- +- if (pll_settings->adjusted_pix_clk == 0) { +- dal_logger_write(calc_pll_cs->ctx->logger, +- LOG_MAJOR_ERROR, +- LOG_MINOR_COMPONENT_GPU, +- "%s Bad requested pixel clock", __func__); +- return MAX_PLL_CALC_ERROR; +- } +- +-/* 1) Find Post divider ranges */ +- if (pll_settings->pix_clk_post_divider) { +- min_post_divider = pll_settings->pix_clk_post_divider; +- max_post_divider = pll_settings->pix_clk_post_divider; +- } else { +- min_post_divider = calc_pll_cs->min_pix_clock_pll_post_divider; +- if (min_post_divider * pll_settings->adjusted_pix_clk < +- calc_pll_cs->min_vco_khz) { +- min_post_divider = calc_pll_cs->min_vco_khz / +- pll_settings->adjusted_pix_clk; +- if ((min_post_divider * +- pll_settings->adjusted_pix_clk) < +- calc_pll_cs->min_vco_khz) +- min_post_divider++; +- } +- +- max_post_divider = calc_pll_cs->max_pix_clock_pll_post_divider; +- if (max_post_divider * pll_settings->adjusted_pix_clk +- > calc_pll_cs->max_vco_khz) +- max_post_divider = calc_pll_cs->max_vco_khz / +- pll_settings->adjusted_pix_clk; +- } +- +-/* 2) Find Reference divider ranges +- * When SS is enabled, or for Display Port even without SS, +- * pll_settings->referenceDivider is not zero. +- * So calculate PPLL FB and fractional FB divider +- * using the passed reference divider*/ +- +- if (pll_settings->reference_divider) { +- min_ref_divider = pll_settings->reference_divider; +- max_ref_divider = pll_settings->reference_divider; +- } else { +- min_ref_divider = ((calc_pll_cs->ref_freq_khz +- / calc_pll_cs->max_pll_input_freq_khz) +- > calc_pll_cs->min_pll_ref_divider) +- ? calc_pll_cs->ref_freq_khz +- / calc_pll_cs->max_pll_input_freq_khz +- : calc_pll_cs->min_pll_ref_divider; +- +- max_ref_divider = ((calc_pll_cs->ref_freq_khz +- / calc_pll_cs->min_pll_input_freq_khz) +- < calc_pll_cs->max_pll_ref_divider) +- ? calc_pll_cs->ref_freq_khz / +- calc_pll_cs->min_pll_input_freq_khz +- : calc_pll_cs->max_pll_ref_divider; +- } +- +-/* If some parameters are invalid we could have scenario when "min">"max" +- * which produced endless loop later. +- * We should investigate why we get the wrong parameters. +- * But to follow the similar logic when "adjustedPixelClock" is set to be 0 +- * it is better to return here than cause system hang/watchdog timeout later. +- * ## SVS Wed 15 Jul 2009 */ +- +- if (min_post_divider > max_post_divider) { +- dal_logger_write(calc_pll_cs->ctx->logger, +- LOG_MAJOR_ERROR, +- LOG_MINOR_COMPONENT_GPU, +- "%s Post divider range is invalid", __func__); +- return MAX_PLL_CALC_ERROR; +- } +- +- if (min_ref_divider > max_ref_divider) { +- dal_logger_write(calc_pll_cs->ctx->logger, +- LOG_MAJOR_ERROR, +- LOG_MINOR_COMPONENT_GPU, +- "%s Reference divider range is invalid", __func__); +- return MAX_PLL_CALC_ERROR; +- } +- +-/* 3) Try to find PLL dividers given ranges +- * starting with minimal error tolerance. +- * Increase error tolerance until PLL dividers found*/ +- err_tolerance = MAX_PLL_CALC_ERROR; +- +- while (!calc_pll_dividers_in_range( +- calc_pll_cs, +- pll_settings, +- min_ref_divider, +- max_ref_divider, +- min_post_divider, +- max_post_divider, +- err_tolerance)) +- err_tolerance += (err_tolerance > 10) +- ? (err_tolerance / 10) +- : 1; +- +- return err_tolerance; +-} +- +-static bool calc_pll_clock_source_max_vco_construct( +- struct calc_pll_clock_source *calc_pll_cs, +- struct calc_pll_clock_source_init_data *init_data) +-{ +- +- uint32_t i; +- struct firmware_info fw_info = { { 0 } }; +- if (calc_pll_cs == NULL || +- init_data == NULL || +- init_data->bp == NULL) +- return false; +- +- if (init_data->bp->funcs->get_firmware_info( +- init_data->bp, +- &fw_info) != BP_RESULT_OK) +- return false; +- +- calc_pll_cs->ctx = init_data->ctx; +- calc_pll_cs->ref_freq_khz = fw_info.pll_info.crystal_frequency; +- calc_pll_cs->min_vco_khz = +- fw_info.pll_info.min_output_pxl_clk_pll_frequency; +- calc_pll_cs->max_vco_khz = +- fw_info.pll_info.max_output_pxl_clk_pll_frequency; +- +- if (init_data->max_override_input_pxl_clk_pll_freq_khz != 0) +- calc_pll_cs->max_pll_input_freq_khz = +- init_data->max_override_input_pxl_clk_pll_freq_khz; +- else +- calc_pll_cs->max_pll_input_freq_khz = +- fw_info.pll_info.max_input_pxl_clk_pll_frequency; +- +- if (init_data->min_override_input_pxl_clk_pll_freq_khz != 0) +- calc_pll_cs->min_pll_input_freq_khz = +- init_data->min_override_input_pxl_clk_pll_freq_khz; +- else +- calc_pll_cs->min_pll_input_freq_khz = +- fw_info.pll_info.min_input_pxl_clk_pll_frequency; +- +- calc_pll_cs->min_pix_clock_pll_post_divider = +- init_data->min_pix_clk_pll_post_divider; +- calc_pll_cs->max_pix_clock_pll_post_divider = +- init_data->max_pix_clk_pll_post_divider; +- calc_pll_cs->min_pll_ref_divider = +- init_data->min_pll_ref_divider; +- calc_pll_cs->max_pll_ref_divider = +- init_data->max_pll_ref_divider; +- +- if (init_data->num_fract_fb_divider_decimal_point == 0 || +- init_data->num_fract_fb_divider_decimal_point_precision > +- init_data->num_fract_fb_divider_decimal_point) { +- dal_logger_write(calc_pll_cs->ctx->logger, +- LOG_MAJOR_ERROR, +- LOG_MINOR_COMPONENT_GPU, +- "The dec point num or precision is incorrect!"); +- return false; +- } +- if (init_data->num_fract_fb_divider_decimal_point_precision == 0) { +- dal_logger_write(calc_pll_cs->ctx->logger, +- LOG_MAJOR_ERROR, +- LOG_MINOR_COMPONENT_GPU, +- "Incorrect fract feedback divider precision num!"); +- return false; +- } +- +- calc_pll_cs->fract_fb_divider_decimal_points_num = +- init_data->num_fract_fb_divider_decimal_point; +- calc_pll_cs->fract_fb_divider_precision = +- init_data->num_fract_fb_divider_decimal_point_precision; +- calc_pll_cs->fract_fb_divider_factor = 1; +- for (i = 0; i < calc_pll_cs->fract_fb_divider_decimal_points_num; ++i) +- calc_pll_cs->fract_fb_divider_factor *= 10; +- +- calc_pll_cs->fract_fb_divider_precision_factor = 1; +- for ( +- i = 0; +- i < (calc_pll_cs->fract_fb_divider_decimal_points_num - +- calc_pll_cs->fract_fb_divider_precision); +- ++i) +- calc_pll_cs->fract_fb_divider_precision_factor *= 10; +- +- return true; +-} +- +-bool dal_calc_pll_clock_source_max_vco_init( +- struct calc_pll_clock_source *calc_pll_cs, +- struct calc_pll_clock_source_init_data *init_data) +-{ +- return calc_pll_clock_source_max_vco_construct( +- calc_pll_cs, init_data); +-} +- +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.h b/drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.h +deleted file mode 100644 +index 48db3d6..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/calc_pll_clock_source.h ++++ /dev/null +@@ -1,81 +0,0 @@ +-/* Copyright 2012-15 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 __DAL_CALC_PLL_CLOCK_SOURCE_H__ +-#define __DAL_CALC_PLL_CLOCK_SOURCE_H__ +- +-#include "dc_bios_types.h" +- +-#include "include/clock_source_types.h" +- +-struct calc_pll_clock_source_init_data { +- struct dc_bios *bp; +- uint32_t min_pix_clk_pll_post_divider; +- uint32_t max_pix_clk_pll_post_divider; +- uint32_t min_pll_ref_divider; +- uint32_t max_pll_ref_divider; +- uint32_t min_override_input_pxl_clk_pll_freq_khz; +-/* if not 0, override the firmware info */ +- +- uint32_t max_override_input_pxl_clk_pll_freq_khz; +-/* if not 0, override the firmware info */ +- +- uint32_t num_fract_fb_divider_decimal_point; +-/* number of decimal point for fractional feedback divider value */ +- +- uint32_t num_fract_fb_divider_decimal_point_precision; +-/* number of decimal point to round off for fractional feedback divider value*/ +- struct dc_context *ctx; +- +-}; +-#define CALC_PLL_CLK_SRC_ERR_TOLERANCE 1 +-struct calc_pll_clock_source { +- uint32_t ref_freq_khz; +- uint32_t min_pix_clock_pll_post_divider; +- uint32_t max_pix_clock_pll_post_divider; +- uint32_t min_pll_ref_divider; +- uint32_t max_pll_ref_divider; +- +- uint32_t max_vco_khz; +- uint32_t min_vco_khz; +- uint32_t min_pll_input_freq_khz; +- uint32_t max_pll_input_freq_khz; +- +- uint32_t fract_fb_divider_decimal_points_num; +- uint32_t fract_fb_divider_factor; +- uint32_t fract_fb_divider_precision; +- uint32_t fract_fb_divider_precision_factor; +- struct dc_context *ctx; +-}; +- +- +-bool dal_calc_pll_clock_source_max_vco_init( +- struct calc_pll_clock_source *calc_pll_cs, +- struct calc_pll_clock_source_init_data *init_data); +- +-uint32_t dal_clock_source_calculate_pixel_clock_pll_dividers( +- struct calc_pll_clock_source *calc_pll_cs, +- struct pll_settings *pll_settings); +- +- +-#endif /*__DAL_CALC_PLL_CLOCK_SOURCE_H__*/ +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/clock_source.h b/drivers/gpu/drm/amd/dal/dc/gpu/clock_source.h +deleted file mode 100644 +index a7863cd..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/clock_source.h ++++ /dev/null +@@ -1,141 +0,0 @@ +-/* +- * Copyright 2012-15 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 __DAL_CLOCK_SOURCE_H__ +-#define __DAL_CLOCK_SOURCE_H__ +- +-#include "include/adapter_service_types.h" +-#include "include/bios_parser_types.h" +-#include "include/clock_source_interface.h" +-#include "include/clock_source_types.h" +- +-struct spread_spectrum_data { +- uint32_t percentage; /*> In unit of 0.01% or 0.001%*/ +- uint32_t percentage_divider; /*> 100 or 1000 */ +- uint32_t freq_range_khz; +- uint32_t modulation_freq_hz; +- +- struct spread_spectrum_flags flags; +-}; +- +-struct clock_source_impl { +- bool (*switch_dp_clock_source)( +- struct clock_source *clk_src, +- enum controller_id, +- enum clock_source_id); +- bool (*adjust_pll_pixel_rate)( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- uint32_t requested_pix_clk_hz); +- bool (*adjust_dto_pixel_rate)( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- uint32_t requested_clk_freq_hz); +- uint32_t (*retrieve_dto_pix_rate_hz)( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params); +- uint32_t (*retrieve_pll_pix_rate_hz)( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params); +- +- uint32_t (*get_pix_clk_dividers)(struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings); +- bool (*program_pix_clk)(struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings); +- bool (*power_down_pll)(struct clock_source *clk_src, +- enum controller_id); +- void (*destroy)(struct clock_source **clk_src); +-}; +- +-void dal_clock_source_get_ss_info_from_atombios( +- struct clock_source *clk_src, +- enum as_signal_type as_signal, +- struct spread_spectrum_data *ss_data[], +- uint32_t *ss_entries_num); +-uint32_t dal_clock_source_base_retrieve_dto_pix_rate_hz( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params); +-const struct spread_spectrum_data *dal_clock_source_get_ss_data_entry( +- struct clock_source *clk_src, +- enum signal_type signal, +- uint32_t pix_clk_khz); +-/* for PLL and EXT clock sources */ +-struct registers { +- uint32_t dp_dtox_phase; +- uint32_t dp_dtox_modulo; +- uint32_t crtcx_pixel_rate_cntl; +- uint32_t crtcx_phypll_pixel_rate_cntl; +- uint32_t combophyx_pll_wrap_cntl; +- uint32_t combophyx_freq_cntl0; +- uint32_t combophyx_freq_cntl2; +- uint32_t combophyx_freq_cntl3; +-}; +- +-struct clock_source { +- const struct clock_source_impl *funcs; +- struct graphics_object_id id; +- enum clock_source_id clk_src_id; +- struct adapter_service *adapter_service; +- struct dc_bios *bios_parser; +- +- struct spread_spectrum_data *ep_ss_params; +- uint32_t ep_ss_params_cnt; +- struct spread_spectrum_data *dp_ss_params; +- uint32_t dp_ss_params_cnt; +- +- struct spread_spectrum_data *hdmi_ss_params; +- uint32_t hdmi_ss_params_cnt; +- +- struct spread_spectrum_data *dvi_ss_params; +- uint32_t dvi_ss_params_cnt; +- +- uint32_t output_signals; +- uint32_t input_signals; +- +- bool turn_off_ds; +- bool is_gen_lock_capable; /*replacement for virtual method*/ +- bool is_clock_source_with_fixed_freq; /*replacement for virtual method*/ +- enum clock_sharing_level clk_sharing_lvl; +- struct dc_context *ctx; +-}; +- +-bool dal_clock_source_construct( +- struct clock_source *clk_src, +- struct clock_source_init_data *clk_src_init_data); +-bool dal_clock_source_base_adjust_pll_pixel_rate( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- uint32_t requested_pix_clk_hz); +-bool dal_clock_source_base_adjust_dto_pix_rate( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- uint32_t requested_pix_clk_hz); +-uint32_t dal_clock_source_base_retrieve_pll_pix_rate_hz( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params); +- +-#endif +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.c +deleted file mode 100644 +index fa3201b..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.c ++++ /dev/null +@@ -1,383 +0,0 @@ +-/* Copyright 2012-15 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 "dc_services.h" +- +-#include "dce/dce_11_0_d.h" +-#include "dce/dce_11_0_sh_mask.h" +- +-#include "include/logger_interface.h" +-#include "include/adapter_service_interface.h" +-#include "include/fixed32_32.h" +- +-#include "ext_clock_source_dce110.h" +- +-/** +- * In this file ECS stands for External Clock Source. +- */ +- +-#define ECS110_FROM_BASE(clk_src_ptr)\ +- container_of(\ +- container_of((clk_src_ptr), struct ext_clock_source, base), \ +- struct ext_clock_source_dce110, base) +- +-#define ECS_WARNING(...) \ +- dal_logger_write(ctx->logger, LOG_MAJOR_WARNING, \ +- LOG_MINOR_COMPONENT_GPU, __VA_ARGS__) +- +-#define ECS_ERROR(...) \ +- dal_logger_write(ctx->logger, LOG_MAJOR_ERROR, \ +- LOG_MINOR_COMPONENT_GPU, __VA_ARGS__) +- +-/****************************************************************************** +- * implementation functions +- *****************************************************************************/ +- +-static uint32_t controller_id_to_index( +- struct clock_source *clk_src, +- enum controller_id controller_id) +-{ +- struct dc_context *ctx = clk_src->ctx; +- uint32_t index = 0; +- +- switch (controller_id) { +- case CONTROLLER_ID_D0: +- index = 0; +- break; +- case CONTROLLER_ID_D1: +- index = 1; +- break; +- case CONTROLLER_ID_D2: +- index = 2; +- break; +- default: +- ECS_ERROR("%s: invalid input controller_id = %d!\n", +- __func__, controller_id); +- break; +- } +- +- return index; +-} +- +-/* Adjust pixel rate by DTO programming (used for DisplayPort) */ +-static bool adjust_dto_pixel_rate( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- uint32_t requested_pix_clk_hz) +-{ +- struct ext_clock_source_dce110 *ecs110 = +- ECS110_FROM_BASE(clk_src); +- struct dc_context *ctx = clk_src->ctx; +- uint32_t index; +- uint32_t dto_phase_reg; +- uint32_t dto_modulo_reg; +- uint32_t dto_phase_rnd; +- uint32_t addr; +- uint32_t value; +- struct fixed32_32 dto_phase; +- +- if (NULL == pix_clk_params) { +- ECS_WARNING("%s: invalid input!\n", __func__); +- return false; +- } +- +- index = controller_id_to_index(clk_src, pix_clk_params->controller_id); +- +- addr = ecs110->registers[index].dp_dtox_phase; +- dto_phase_reg = dal_read_reg(ctx, addr); +- +- addr = ecs110->registers[index].dp_dtox_modulo; +- dto_modulo_reg = dal_read_reg(ctx, addr); +- +- if (!dto_modulo_reg) { +- ECS_WARNING("%s: current modulo is zero!\n", __func__); +- return false; +- } +- +- dto_phase = dal_fixed32_32_from_int(requested_pix_clk_hz); +- +- dto_phase = dal_fixed32_32_mul_int(dto_phase, dto_modulo_reg); +- +- dto_phase = dal_fixed32_32_div_int(dto_phase, +- pix_clk_params->dp_ref_clk * 1000); +- +- dto_phase_rnd = dal_fixed32_32_round(dto_phase); +- +- /* Program DTO Phase */ +- if (dto_phase_reg != dto_phase_rnd) { +- /* If HW De-Spreading enabled on DP REF clock and if there will +- * be case when Pixel rate > average DP Ref Clock, then need to +- * disable de-spread for DP DTO (ATOMBIOS will program MODULO +- * for average DP REF clock so no further SW adjustment +- * needed) */ +- if (pix_clk_params->de_spread_params.hw_dso_n_dp_ref_clk) { +- +- addr = ecs110->registers[index].crtcx_pixel_rate_cntl; +- value = dal_read_reg(ctx, addr); +- +- if (requested_pix_clk_hz / 1000 > +- pix_clk_params-> +- de_spread_params.avg_dp_ref_clk_khz) { +- +- set_reg_field_value(value, 1, +- CRTC0_PIXEL_RATE_CNTL, +- DP_DTO0_DS_DISABLE); +- } else { +- set_reg_field_value(value, 0, +- CRTC0_PIXEL_RATE_CNTL, +- DP_DTO0_DS_DISABLE); +- } +- +- dal_write_reg(ctx, addr, value); +- } +- +- value = 0; +- addr = ecs110->registers[index].dp_dtox_phase; +- +- set_reg_field_value(value, dto_phase_rnd, +- DP_DTO0_PHASE, +- DP_DTO0_PHASE); +- +- dal_write_reg(ctx, addr, value); +- } +- +- return true; +-} +- +-/** +- * Retrieve Pixel Rate (in Hz) from HW registers already programmed. +- */ +-static uint32_t retrieve_dp_pixel_rate_from_display_pll( +- struct clock_source *clk_src, +- struct pixel_clk_params *params) +-{ +- struct dc_context *ctx = clk_src->ctx; +- +- /* TODO: update when DAL2 implements this function. */ +- DAL_LOGGER_NOT_IMPL(LOG_MINOR_COMPONENT_GPU, "%s\n", __func__); +- return 0; +-} +- +-static uint32_t retrieve_dto_pix_rate_hz( +- struct clock_source *clk_src, +- struct pixel_clk_params *params) +-{ +- struct ext_clock_source_dce110 *ecs110 = +- ECS110_FROM_BASE(clk_src); +- struct dc_context *ctx = clk_src->ctx; +- uint32_t index; +- uint32_t dto_phase_reg; +- uint32_t dto_modulo_reg; +- uint32_t addr; +- uint32_t value; +- uint32_t pix_rate_hz; +- struct fixed32_32 p_clk; +- +- if (params == NULL) +- return 0; +- +- if (NULL == params) { +- ECS_WARNING("%s: invalid input!\n", __func__); +- return false; +- } +- +- index = controller_id_to_index(clk_src, params->controller_id); +- +- addr = ecs110->registers[index].crtcx_pixel_rate_cntl; +- value = dal_read_reg(ctx, addr); +- +- if (get_reg_field_value(value, CRTC0_PIXEL_RATE_CNTL, DP_DTO0_ENABLE) +- == 1) { +- +- addr = ecs110->registers[index].dp_dtox_phase; +- dto_phase_reg = dal_read_reg(ctx, addr); +- +- addr = ecs110->registers[index].dp_dtox_modulo; +- dto_modulo_reg = dal_read_reg(ctx, addr); +- +- if (!dto_modulo_reg) { +- ECS_WARNING("%s: current modulo is zero!\n", __func__); +- return 0; +- } +- +- /* Calculate pixel clock from DTO Phase & Modulo*/ +- p_clk = dal_fixed32_32_from_int(params->dp_ref_clk * 1000); +- +- p_clk = dal_fixed32_32_mul_int(p_clk, dto_phase_reg); +- +- p_clk = dal_fixed32_32_div_int(p_clk, dto_modulo_reg); +- +- pix_rate_hz = dal_fixed32_32_round(p_clk); +- } else { +- pix_rate_hz = retrieve_dp_pixel_rate_from_display_pll(clk_src, +- params); +- } +- +- return pix_rate_hz; +-} +- +-/****************************************************************************** +- * create/destroy functions +- *****************************************************************************/ +- +-static void destruct(struct ext_clock_source_dce110 *ecs110) +-{ +- struct ext_clock_source *ext_cs = &ecs110->base; +- struct clock_source *base = &ext_cs->base; +- +- if (NULL != base->dp_ss_params) { +- dc_service_free(base->ctx, base->dp_ss_params); +- base->dp_ss_params = NULL; +- } +- +- dc_service_free(base->ctx, ecs110->registers); +- ecs110->registers = NULL; +-} +- +- +-static void destroy(struct clock_source **clk_src) +-{ +- struct ext_clock_source_dce110 *ecs110; +- +- ecs110 = ECS110_FROM_BASE(*clk_src); +- +- destruct(ecs110); +- +- dc_service_free((*clk_src)->ctx, ecs110); +- +- *clk_src = NULL; +-} +- +-static const struct clock_source_impl funcs = { +- .program_pix_clk = dal_ext_clock_source_program_pix_clk, +- .adjust_pll_pixel_rate = dal_clock_source_base_adjust_pll_pixel_rate, +- .adjust_dto_pixel_rate = adjust_dto_pixel_rate, +- .retrieve_pll_pix_rate_hz = +- dal_clock_source_base_retrieve_pll_pix_rate_hz, +- .get_pix_clk_dividers = dal_ext_clock_source_get_pix_clk_dividers, +- .destroy = destroy, +- .retrieve_dto_pix_rate_hz = retrieve_dto_pix_rate_hz, +- .power_down_pll = dal_ext_clock_source_power_down_pll +-}; +- +-static bool construct( +- struct ext_clock_source_dce110 *ecs110, +- struct clock_source_init_data *clk_src_init_data) +-{ +- struct dc_context *ctx = clk_src_init_data->ctx; +- struct ext_clock_source *ext_cs = &ecs110->base; +- struct clock_source *base = &ext_cs->base; +- uint32_t controllers_num; +- struct registers *registers; +- +- /* None of the base construct() functions allocates memory. +- * That means, in case of error, we don't have to free memory +- * allocated by base. */ +- if (!dal_ext_clock_source_construct(ext_cs, clk_src_init_data)) +- return false; +- +- base->funcs = &funcs; +- +- base->is_gen_lock_capable = false; +- base->dp_ss_params = NULL; +- base->dp_ss_params_cnt = 0; +- +- ecs110->registers = NULL; +- +- if (base->clk_src_id != CLOCK_SOURCE_ID_EXTERNAL) { +- ECS_ERROR("ECS110:Invalid ClockSourceId = %d!\n", +- base->clk_src_id); +- return false; +- } +- +- controllers_num = dal_adapter_service_get_controllers_num( +- base->adapter_service); +- +- if (controllers_num <= 0 || controllers_num > 6) { +- ECS_ERROR("ECS110:Invalid number of controllers = %d!\n", +- controllers_num); +- return false; +- } +- +- ecs110->registers = (struct registers *) +- (dc_service_alloc(clk_src_init_data->ctx, sizeof(struct registers) * controllers_num)); +- +- if (ecs110->registers == NULL) { +- ECS_ERROR("ECS110:Failed to allocate 'registers'!\n"); +- return false; +- } +- +- registers = ecs110->registers; +- +- /* Assign register address. No break between cases */ +- switch (controllers_num) { +- case 3: +- registers[2].dp_dtox_phase = mmDP_DTO2_PHASE; +- registers[2].dp_dtox_modulo = mmDP_DTO2_MODULO; +- registers[2].crtcx_pixel_rate_cntl = mmCRTC2_PIXEL_RATE_CNTL; +- /* fallthrough */ +- case 2: +- registers[1].dp_dtox_phase = mmDP_DTO1_PHASE; +- registers[1].dp_dtox_modulo = mmDP_DTO1_MODULO; +- registers[1].crtcx_pixel_rate_cntl = mmCRTC1_PIXEL_RATE_CNTL; +- /* fallthrough */ +- case 1: +- registers[0].dp_dtox_phase = mmDP_DTO0_PHASE; +- registers[0].dp_dtox_modulo = mmDP_DTO0_MODULO; +- registers[0].crtcx_pixel_rate_cntl = mmCRTC0_PIXEL_RATE_CNTL; +- break; +- +- default: +- /* We can not get here because we checked number of +- * controllers already. */ +- break; +- } +- +- dal_clock_source_get_ss_info_from_atombios( +- base, +- AS_SIGNAL_TYPE_DISPLAY_PORT, +- &base->dp_ss_params, +- &base->dp_ss_params_cnt); +- +- return true; +-} +- +- +-struct clock_source *dal_ext_clock_source_dce110_create( +- struct clock_source_init_data *clk_src_init_data) +-{ +- struct ext_clock_source_dce110 *ecs110; +- +- ecs110 = dc_service_alloc(clk_src_init_data->ctx, sizeof(struct ext_clock_source_dce110)); +- +- if (ecs110 == NULL) +- return NULL; +- +- if (!construct(ecs110, clk_src_init_data)) { +- dc_service_free(clk_src_init_data->ctx, ecs110); +- return NULL; +- } +- +- return &ecs110->base.base; +-} +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.h +deleted file mode 100644 +index 4ea2ae2..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/ext_clock_source_dce110.h ++++ /dev/null +@@ -1,38 +0,0 @@ +-/* Copyright 2012-15 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 __DAL_EXT_CLOCK_SOURCE_DCE110__ +-#define __DAL_EXT_CLOCK_SOURCE_DCE110__ +- +-#include "../ext_clock_source.h" +- +-struct ext_clock_source_dce110 { +- struct ext_clock_source base; +- struct registers *registers; +-}; +- +-struct clock_source *dal_ext_clock_source_dce110_create( +- struct clock_source_init_data *clk_src_init_data); +- +-#endif /*__DAL_EXT_CLOCK_SOURCE_DCE110__*/ +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.c +deleted file mode 100644 +index ba05597..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.c ++++ /dev/null +@@ -1,718 +0,0 @@ +-/* Copyright 2012-15 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 "dc_services.h" +- +-#include "dce/dce_11_0_d.h" +-#include "dce/dce_11_0_sh_mask.h" +- +-#include "include/logger_interface.h" +-#include "include/bios_parser_interface.h" +-#include "include/adapter_service_interface.h" +-#include "include/fixed32_32.h" +-#include "gpu/calc_pll_clock_source.h" +-#include "gpu/clock_source.h" +-#include "gpu/pll_clock_source.h" +- +-#include "gpu/dce110/pll_clock_source_dce110.h" +- +-enum fract_fb_divider_dec_points { +- FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM = 6, +- FRACT_FB_DIVIDER_DEC_POINTS_NO_DS_NUM = 1, +-}; +- +-#define FROM_CLK_SRC(clk_src_ptr)\ +- container_of(\ +- container_of((clk_src_ptr), struct pll_clock_source, base), \ +- struct pll_clock_source_dce110, base) +- +-static bool calculate_ss( +- struct pll_clock_source_dce110 *clk_src, +- struct pll_settings *pll_settings, +- const struct spread_spectrum_data *ss_data, +- struct delta_sigma_data *ds_data) +-{ +- struct fixed32_32 fb_div; +- struct fixed32_32 ss_amount; +- struct fixed32_32 ss_nslip_amount; +- struct fixed32_32 ss_ds_frac_amount; +- struct fixed32_32 ss_step_size; +- struct fixed32_32 modulation_time; +- +- if (ds_data == NULL) +- return false; +- if (ss_data == NULL) +- return false; +- if (ss_data->percentage == 0) +- return false; +- if (pll_settings == NULL) +- return false; +- +- +- dc_service_memset(ds_data, 0, sizeof(struct delta_sigma_data)); +- +- +- +- /* compute SS_AMOUNT_FBDIV & SS_AMOUNT_NFRAC_SLIP & SS_AMOUNT_DSFRAC*/ +- /* 6 decimal point support in fractional feedback divider */ +- fb_div = dal_fixed32_32_from_fraction( +- pll_settings->fract_feedback_divider, 1000000); +- fb_div = dal_fixed32_32_add_int(fb_div, pll_settings->feedback_divider); +- +- ds_data->ds_frac_amount = 0; +- /*spreadSpectrumPercentage is in the unit of .01%, +- * so have to divided by 100 * 100*/ +- ss_amount = dal_fixed32_32_mul( +- fb_div, dal_fixed32_32_from_fraction(ss_data->percentage, +- 100 * ss_data->percentage_divider)); +- ds_data->feedback_amount = dal_fixed32_32_floor(ss_amount); +- +- ss_nslip_amount = dal_fixed32_32_sub(ss_amount, +- dal_fixed32_32_from_int(ds_data->feedback_amount)); +- ss_nslip_amount = dal_fixed32_32_mul_int(ss_nslip_amount, 10); +- ds_data->nfrac_amount = dal_fixed32_32_floor(ss_nslip_amount); +- +- ss_ds_frac_amount = dal_fixed32_32_sub(ss_nslip_amount, +- dal_fixed32_32_from_int(ds_data->nfrac_amount)); +- ss_ds_frac_amount = dal_fixed32_32_mul_int(ss_ds_frac_amount, 65536); +- ds_data->ds_frac_amount = dal_fixed32_32_floor(ss_ds_frac_amount); +- +- /* compute SS_STEP_SIZE_DSFRAC */ +- modulation_time = dal_fixed32_32_from_fraction( +- pll_settings->reference_freq * 1000, +- pll_settings->reference_divider * ss_data->modulation_freq_hz); +- +- +- if (ss_data->flags.CENTER_SPREAD) +- modulation_time = dal_fixed32_32_div_int(modulation_time, 4); +- else +- modulation_time = dal_fixed32_32_div_int(modulation_time, 2); +- +- ss_step_size = dal_fixed32_32_div(ss_amount, modulation_time); +- /* SS_STEP_SIZE_DSFRAC_DEC = Int(SS_STEP_SIZE * 2 ^ 16 * 10)*/ +- ss_step_size = dal_fixed32_32_mul_int(ss_step_size, 65536 * 10); +- ds_data->ds_frac_size = dal_fixed32_32_floor(ss_step_size); +- +- return true; +-} +- +-static bool disable_spread_spectrum(struct pll_clock_source_dce110 *clk_src) +-{ +- enum bp_result result; +- struct bp_spread_spectrum_parameters bp_ss_params = {0}; +- struct clock_source *clock_source = NULL; +- +- clock_source = &clk_src->base.base; +- bp_ss_params.pll_id = clock_source->clk_src_id; +- +- /*Call ASICControl to process ATOMBIOS Exec table*/ +- result = clock_source->bios_parser->funcs->enable_spread_spectrum_on_ppll( +- clock_source->bios_parser, +- &bp_ss_params, +- false); +- +- return result == BP_RESULT_OK; +-} +- +-static bool enable_spread_spectrum( +- struct pll_clock_source_dce110 *clk_src, +- enum signal_type signal, struct pll_settings *pll_settings) +-{ +- struct bp_spread_spectrum_parameters bp_params = {0}; +- struct delta_sigma_data d_s_data; +- struct clock_source *clock_source = NULL; +- const struct spread_spectrum_data *ss_data = NULL; +- +- clock_source = &clk_src->base.base; +- ss_data = dal_clock_source_get_ss_data_entry( +- clock_source, +- signal, +- pll_settings->calculated_pix_clk); +- +-/* Pixel clock PLL has been programmed to generate desired pixel clock, +- * now enable SS on pixel clock */ +-/* TODO is it OK to return true not doing anything ??*/ +- if (ss_data != NULL && pll_settings->ss_percentage != 0) { +- if (calculate_ss(clk_src, pll_settings, ss_data, &d_s_data)) { +- bp_params.ds.feedback_amount = +- d_s_data.feedback_amount; +- bp_params.ds.nfrac_amount = +- d_s_data.nfrac_amount; +- bp_params.ds.ds_frac_size = d_s_data.ds_frac_size; +- bp_params.ds_frac_amount = +- d_s_data.ds_frac_amount; +- bp_params.flags.DS_TYPE = 1; +- bp_params.pll_id = clock_source->clk_src_id; +- bp_params.percentage = ss_data->percentage; +- if (ss_data->flags.CENTER_SPREAD) +- bp_params.flags.CENTER_SPREAD = 1; +- if (ss_data->flags.EXTERNAL_SS) +- bp_params.flags.EXTERNAL_SS = 1; +- +- if (BP_RESULT_OK != +- clock_source->bios_parser->funcs->enable_spread_spectrum_on_ppll( +- clock_source->bios_parser, +- &bp_params, +- true)) +- return false; +- } else +- return false; +- } +- return true; +-} +- +-static void program_pixel_clk_resync( +- struct pll_clock_source_dce110 *clk_src, +- enum signal_type signal_type, +- enum dc_color_depth colordepth) +-{ +- struct clock_source *clock_source = NULL; +- uint32_t value = 0; +- +- clock_source = &clk_src->base.base; +- +- value = dal_read_reg( +- clock_source->ctx, +- clk_src->pixclkx_resync_cntl); +- +- set_reg_field_value( +- value, +- 0, +- PIXCLK1_RESYNC_CNTL, +- DCCG_DEEP_COLOR_CNTL1); +- +- /* +- 24 bit mode: TMDS clock = 1.0 x pixel clock (1:1) +- 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4) +- 36 bit mode: TMDS clock = 1.5 x pixel clock (3:2) +- 48 bit mode: TMDS clock = 2 x pixel clock (2:1) +- */ +- if (signal_type != SIGNAL_TYPE_HDMI_TYPE_A) +- return; +- +- switch (colordepth) { +- case COLOR_DEPTH_888: +- set_reg_field_value( +- value, +- 0, +- PIXCLK1_RESYNC_CNTL, +- DCCG_DEEP_COLOR_CNTL1); +- break; +- case COLOR_DEPTH_101010: +- set_reg_field_value( +- value, +- 1, +- PIXCLK1_RESYNC_CNTL, +- DCCG_DEEP_COLOR_CNTL1); +- break; +- case COLOR_DEPTH_121212: +- set_reg_field_value( +- value, +- 2, +- PIXCLK1_RESYNC_CNTL, +- DCCG_DEEP_COLOR_CNTL1); +- break; +- case COLOR_DEPTH_161616: +- set_reg_field_value( +- value, +- 3, +- PIXCLK1_RESYNC_CNTL, +- DCCG_DEEP_COLOR_CNTL1); +- break; +- default: +- break; +- } +- +- dal_write_reg( +- clock_source->ctx, +- clk_src->pixclkx_resync_cntl, +- value); +-} +- +-static bool program_pix_clk( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings) +-{ +- struct pll_clock_source_dce110 *pll_clk_src_dce110 = +- FROM_CLK_SRC(clk_src); +- struct bp_pixel_clock_parameters bp_pc_params = {0}; +- +- /* First disable SS +- * ATOMBIOS will enable by default SS on PLL for DP, +- * do not disable it here +- */ +- if (!dc_is_dp_signal(pix_clk_params->signal_type)) +- disable_spread_spectrum(pll_clk_src_dce110); +- +- /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/ +- bp_pc_params.controller_id = pix_clk_params->controller_id; +- bp_pc_params.pll_id = clk_src->clk_src_id; +- bp_pc_params.target_pixel_clock = +- pll_settings->actual_pix_clk; +- bp_pc_params.reference_divider = pll_settings->reference_divider; +- bp_pc_params.feedback_divider = pll_settings->feedback_divider; +- bp_pc_params.fractional_feedback_divider = +- pll_settings->fract_feedback_divider; +- bp_pc_params.pixel_clock_post_divider = +- pll_settings->pix_clk_post_divider; +- bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id; +- bp_pc_params.signal_type = pix_clk_params->signal_type; +- bp_pc_params.flags.SET_EXTERNAL_REF_DIV_SRC = +- pll_settings->use_external_clk; +- +- if (clk_src->bios_parser->funcs->set_pixel_clock(clk_src->bios_parser, +- &bp_pc_params) != BP_RESULT_OK) +- return false; +- +-/* Enable SS +- * ATOMBIOS will enable by default SS for DP on PLL ( DP ID clock), +- * based on HW display PLL team, SS control settings should be programmed +- * during PLL Reset, but they do not have effect +- * until SS_EN is asserted.*/ +- if (pix_clk_params->flags.ENABLE_SS && !dc_is_dp_signal( +- pix_clk_params->signal_type)) +- if (!enable_spread_spectrum(pll_clk_src_dce110, +- pix_clk_params->signal_type, +- pll_settings)) +- return false; +- +-/* Resync deep color DTO */ +- program_pixel_clk_resync(pll_clk_src_dce110, +- pix_clk_params->signal_type, +- pix_clk_params->color_depth); +- +- return true; +-} +- +-static void ss_info_from_atombios_destroy( +- struct pll_clock_source_dce110 *clk_src) +-{ +- struct clock_source *cs = &clk_src->base.base; +- +- if (NULL != cs->ep_ss_params) { +- dc_service_free(cs->ctx, cs->ep_ss_params); +- cs->ep_ss_params = NULL; +- } +- +- if (NULL != cs->dp_ss_params) { +- dc_service_free(cs->ctx, cs->dp_ss_params); +- cs->dp_ss_params = NULL; +- } +- +- if (NULL != cs->hdmi_ss_params) { +- dc_service_free(cs->ctx, cs->hdmi_ss_params); +- cs->hdmi_ss_params = NULL; +- } +- +- if (NULL != cs->dvi_ss_params) { +- dc_service_free(cs->ctx, cs->dvi_ss_params); +- cs->dvi_ss_params = NULL; +- } +-} +- +-static void destruct( +- struct pll_clock_source_dce110 *pll_cs) +-{ +- ss_info_from_atombios_destroy(pll_cs); +- +- if (NULL != pll_cs->registers) { +- dc_service_free(pll_cs->base.base.ctx, pll_cs->registers); +- pll_cs->registers = NULL; +- } +-} +- +-static void destroy(struct clock_source **clk_src) +-{ +- struct pll_clock_source_dce110 *pll_clk_src; +- +- pll_clk_src = FROM_CLK_SRC(*clk_src); +- +- destruct(pll_clk_src); +- dc_service_free((*clk_src)->ctx, pll_clk_src); +- +- *clk_src = NULL; +-} +- +-/** +- * Calculate PLL Dividers for given Clock Value. +- * First will call VBIOS Adjust Exec table to check if requested Pixel clock +- * will be Adjusted based on usage. +- * Then it will calculate PLL Dividers for this Adjusted clock using preferred +- * method (Maximum VCO frequency). +- * +- * \return +- * Calculation error in units of 0.01% +- */ +-static uint32_t get_pix_clk_dividers( +- struct clock_source *cs, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings) +-{ +- struct pll_clock_source_dce110 *pll_cs_110 = FROM_CLK_SRC(cs); +- struct pll_clock_source *pll_base = &pll_cs_110->base; +- uint32_t pll_calc_error = MAX_PLL_CALC_ERROR; +- uint32_t addr = 0; +- uint32_t value = 0; +- uint32_t field = 0; +- +- if (pix_clk_params == NULL || pll_settings == NULL +- || pix_clk_params->requested_pix_clk == 0) { +- dal_logger_write(cs->ctx->logger, +- LOG_MAJOR_ERROR, +- LOG_MINOR_COMPONENT_GPU, +- "%s: Invalid parameters!!\n", __func__); +- return pll_calc_error; +- } +- +- dc_service_memset(pll_settings, 0, sizeof(*pll_settings)); +- +- /* Check if reference clock is external (not pcie/xtalin) +- * HW Dce80 spec: +- * 00 - PCIE_REFCLK, 01 - XTALIN, 02 - GENERICA, 03 - GENERICB +- * 04 - HSYNCA, 05 - GENLK_CLK, 06 - PCIE_REFCLK +- */ +- addr = pll_cs_110->pxpll_cntl; +- value = dal_read_reg(cs->ctx, addr); +- field = get_reg_field_value(value, PLL_CNTL, PLL_REF_DIV_SRC); +- pll_settings->use_external_clk = (field > 1); +- +- /* VBIOS by default enables DP SS (spread on IDCLK) for DCE 8.0 always +- * (we do not care any more from SI for some older DP Sink which +- * does not report SS support, no known issues) */ +- if ((pix_clk_params->flags.ENABLE_SS) || +- (dc_is_dp_signal(pix_clk_params->signal_type))) { +- +- const struct spread_spectrum_data *ss_data = +- dal_clock_source_get_ss_data_entry( +- cs, +- pix_clk_params->signal_type, +- pll_settings->adjusted_pix_clk); +- +- if (NULL != ss_data) +- pll_settings->ss_percentage = ss_data->percentage; +- } +- +- /* Check VBIOS AdjustPixelClock Exec table */ +- if (!dal_pll_clock_source_adjust_pix_clk(pll_base, +- pix_clk_params, pll_settings)) { +- /* Should never happen, ASSERT and fill up values to be able +- * to continue. */ +- dal_logger_write(cs->ctx->logger, +- LOG_MAJOR_ERROR, +- LOG_MINOR_COMPONENT_GPU, +- "%s: Failed to adjust pixel clock!!", __func__); +- pll_settings->actual_pix_clk = +- pix_clk_params->requested_pix_clk; +- pll_settings->adjusted_pix_clk = +- pix_clk_params->requested_pix_clk; +- +- if (dc_is_dp_signal(pix_clk_params->signal_type)) +- pll_settings->adjusted_pix_clk = 100000; +- } +- +- /* Calculate Dividers */ +- if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) +- /*Calculate Dividers by HDMI object, no SS case or SS case */ +- pll_calc_error = +- dal_clock_source_calculate_pixel_clock_pll_dividers( +- &pll_cs_110->calc_pll_clock_source_hdmi, +- pll_settings); +- else +- /*Calculate Dividers by default object, no SS case or SS case */ +- pll_calc_error = +- dal_clock_source_calculate_pixel_clock_pll_dividers( +- &pll_cs_110->calc_pll_clock_source, +- pll_settings); +- +- return pll_calc_error; +-} +- +-static const struct clock_source_impl funcs = { +- .program_pix_clk = program_pix_clk, +- .adjust_pll_pixel_rate = NULL, +- .adjust_dto_pixel_rate = NULL, +- .retrieve_pll_pix_rate_hz = NULL, +- .get_pix_clk_dividers = get_pix_clk_dividers, +- .destroy = destroy, +- .retrieve_dto_pix_rate_hz = NULL, +- .power_down_pll = dal_pll_clock_source_power_down_pll, +-}; +- +-static void ss_info_from_atombios_create( +- struct pll_clock_source_dce110 *clk_src) +-{ +- struct clock_source *base = &clk_src->base.base; +- +- dal_clock_source_get_ss_info_from_atombios( +- base, +- AS_SIGNAL_TYPE_DISPLAY_PORT, +- &base->dp_ss_params, +- &base->dp_ss_params_cnt); +- dal_clock_source_get_ss_info_from_atombios( +- base, +- AS_SIGNAL_TYPE_LVDS, +- &base->ep_ss_params, +- &base->ep_ss_params_cnt); +- dal_clock_source_get_ss_info_from_atombios( +- base, +- AS_SIGNAL_TYPE_HDMI, +- &base->hdmi_ss_params, +- &base->hdmi_ss_params_cnt); +- dal_clock_source_get_ss_info_from_atombios( +- base, +- AS_SIGNAL_TYPE_DVI, +- &base->dvi_ss_params, +- &base->dvi_ss_params_cnt); +-} +- +- +-static bool construct( +- struct pll_clock_source_dce110 *pll_cs_dce110, +- struct clock_source_init_data *clk_src_init_data) +-{ +- uint32_t controllers_num = 1; +- +-/* structure normally used with PLL ranges from ATOMBIOS; DS on by default */ +- struct calc_pll_clock_source_init_data calc_pll_cs_init_data = { +- dal_adapter_service_get_bios_parser(clk_src_init_data->as), +- 1, /* minPixelClockPLLPostDivider */ +- PLL_POST_DIV__PLL_POST_DIV_PIXCLK_MASK, +- /* maxPixelClockPLLPostDivider*/ +- 1,/* minPLLRefDivider*/ +- PLL_REF_DIV__PLL_REF_DIV_MASK,/* maxPLLRefDivider*/ +- 0, +-/* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ +- 0, +-/* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ +- FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM, +-/*numberOfFractFBDividerDecimalPoints*/ +- FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM, +-/*number of decimal point to round off for fractional feedback divider value*/ +- clk_src_init_data->ctx +- }; +-/*structure for HDMI, no SS or SS% <= 0.06% for 27 MHz Ref clock */ +- struct calc_pll_clock_source_init_data calc_pll_cs_init_data_hdmi = { +- dal_adapter_service_get_bios_parser(clk_src_init_data->as), +- 1, /* minPixelClockPLLPostDivider */ +- PLL_POST_DIV__PLL_POST_DIV_PIXCLK_MASK, +- /* maxPixelClockPLLPostDivider*/ +- 1,/* minPLLRefDivider*/ +- PLL_REF_DIV__PLL_REF_DIV_MASK,/* maxPLLRefDivider*/ +- 13500, +- /* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ +- 27000, +- /* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/ +- FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM, +- /*numberOfFractFBDividerDecimalPoints*/ +- FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM, +-/*number of decimal point to round off for fractional feedback divider value*/ +- clk_src_init_data->ctx +- }; +- +- struct pll_clock_source *base = &pll_cs_dce110->base; +- struct clock_source *superbase = &base->base; +- +- if (!dal_pll_clock_source_construct(base, clk_src_init_data)) { +- ASSERT_CRITICAL(false); +- return false; +- } +- +- superbase->funcs = &funcs; +- +- superbase->is_clock_source_with_fixed_freq = false; +- superbase->clk_sharing_lvl = CLOCK_SHARING_LEVEL_DISPLAY_PORT_SHAREABLE; +- +- pll_cs_dce110->registers = NULL; +- +-/* PLL3 should not be used although it is available in online register spec */ +- if ((superbase->clk_src_id != CLOCK_SOURCE_ID_PLL1) +- && (superbase->clk_src_id != CLOCK_SOURCE_ID_PLL0)) { +- +- +- ASSERT_CRITICAL(false); +- goto failure; +- } +- +-/* From Driver side PLL0 is now used for non DP timing also, +- * so it supports all signals except Wireless. +- * Wireless signal type does not require a PLL clock source, +- * so we will not waste a clock on it. +-*/ +- superbase->output_signals &= ~SIGNAL_TYPE_WIRELESS; +- +- if (!dal_calc_pll_clock_source_max_vco_init( +- &pll_cs_dce110->calc_pll_clock_source, +- &calc_pll_cs_init_data)) { +- ASSERT_CRITICAL(false); +- goto failure; +- } +- +- if (base->ref_freq_khz == 48000) { +- calc_pll_cs_init_data_hdmi. +- min_override_input_pxl_clk_pll_freq_khz = 24000; +- calc_pll_cs_init_data_hdmi. +- max_override_input_pxl_clk_pll_freq_khz = 48000; +- } else if (base->ref_freq_khz == 100000) { +- calc_pll_cs_init_data_hdmi. +- min_override_input_pxl_clk_pll_freq_khz = 25000; +- calc_pll_cs_init_data_hdmi. +- max_override_input_pxl_clk_pll_freq_khz = 50000; +- } +- +- if (!dal_calc_pll_clock_source_max_vco_init( +- &pll_cs_dce110->calc_pll_clock_source_hdmi, +- &calc_pll_cs_init_data_hdmi)) { +- ASSERT_CRITICAL(false); +- goto failure; +- } +- +- switch (superbase->clk_src_id) { +- case CLOCK_SOURCE_ID_PLL0: +- pll_cs_dce110->pixclkx_resync_cntl = mmPIXCLK0_RESYNC_CNTL; +- pll_cs_dce110->ppll_fb_div = mmBPHYC_PLL0_PLL_FB_DIV; +- pll_cs_dce110->ppll_ref_div = mmBPHYC_PLL0_PLL_REF_DIV; +- pll_cs_dce110->ppll_post_div = mmBPHYC_PLL0_PLL_POST_DIV; +- pll_cs_dce110->pxpll_ds_cntl = mmBPHYC_PLL0_PLL_DS_CNTL; +- pll_cs_dce110->pxpll_ss_cntl = mmBPHYC_PLL0_PLL_SS_CNTL; +- pll_cs_dce110->pxpll_ss_dsfrac = +- mmBPHYC_PLL0_PLL_SS_AMOUNT_DSFRAC; +- pll_cs_dce110->pxpll_cntl = mmBPHYC_PLL0_PLL_CNTL; +- break; +- case CLOCK_SOURCE_ID_PLL1: +- pll_cs_dce110->pixclkx_resync_cntl = mmPIXCLK1_RESYNC_CNTL; +- pll_cs_dce110->ppll_fb_div = mmBPHYC_PLL1_PLL_FB_DIV; +- pll_cs_dce110->ppll_ref_div = mmBPHYC_PLL1_PLL_REF_DIV; +- pll_cs_dce110->ppll_post_div = mmBPHYC_PLL1_PLL_POST_DIV; +- pll_cs_dce110->pxpll_ds_cntl = mmBPHYC_PLL1_PLL_DS_CNTL; +- pll_cs_dce110->pxpll_ss_cntl = mmBPHYC_PLL1_PLL_SS_CNTL; +- pll_cs_dce110->pxpll_ss_dsfrac = +- mmBPHYC_PLL1_PLL_SS_AMOUNT_DSFRAC; +- pll_cs_dce110->pxpll_cntl = mmBPHYC_PLL1_PLL_CNTL; +- break; +- case CLOCK_SOURCE_ID_PLL2: +- /* PLL2 is not supported */ +- default: +- break; +- } +- +- controllers_num = dal_adapter_service_get_controllers_num( +- superbase->adapter_service); +- +- pll_cs_dce110->registers = dc_service_alloc( +- clk_src_init_data->ctx, +- sizeof(struct registers) * controllers_num); +- +- if (pll_cs_dce110->registers == NULL) { +- ASSERT_CRITICAL(false); +- goto failure; +- } +- +- /* Assign register address. No break between cases */ +- switch (controllers_num) { +- case 6: +- pll_cs_dce110->registers[5].dp_dtox_phase = +- mmDP_DTO5_PHASE; +- pll_cs_dce110->registers[5].dp_dtox_modulo = +- mmDP_DTO5_MODULO; +- pll_cs_dce110->registers[5].crtcx_pixel_rate_cntl = +- mmCRTC5_PIXEL_RATE_CNTL; +- /* fall through*/ +- +- case 5: +- pll_cs_dce110->registers[4].dp_dtox_phase = +- mmDP_DTO4_PHASE; +- pll_cs_dce110->registers[4].dp_dtox_modulo = +- mmDP_DTO4_MODULO; +- pll_cs_dce110->registers[4].crtcx_pixel_rate_cntl = +- mmCRTC4_PIXEL_RATE_CNTL; +- /* fall through*/ +- +- case 4: +- pll_cs_dce110->registers[3].dp_dtox_phase = +- mmDP_DTO3_PHASE; +- pll_cs_dce110->registers[3].dp_dtox_modulo = +- mmDP_DTO3_MODULO; +- pll_cs_dce110->registers[3].crtcx_pixel_rate_cntl = +- mmCRTC3_PIXEL_RATE_CNTL; +- /* fall through*/ +- +- case 3: +- pll_cs_dce110->registers[2].dp_dtox_phase = +- mmDP_DTO2_PHASE; +- pll_cs_dce110->registers[2].dp_dtox_modulo = +- mmDP_DTO2_MODULO; +- pll_cs_dce110->registers[2].crtcx_pixel_rate_cntl = +- mmCRTC2_PIXEL_RATE_CNTL; +- /* fall through*/ +- +- case 2: +- pll_cs_dce110->registers[1].dp_dtox_phase = +- mmDP_DTO1_PHASE; +- pll_cs_dce110->registers[1].dp_dtox_modulo = +- mmDP_DTO1_MODULO; +- pll_cs_dce110->registers[1].crtcx_pixel_rate_cntl = +- mmCRTC1_PIXEL_RATE_CNTL; +- /* fall through*/ +- +- case 1: +- pll_cs_dce110->registers[0].dp_dtox_phase = +- mmDP_DTO0_PHASE; +- pll_cs_dce110->registers[0].dp_dtox_modulo = +- mmDP_DTO0_MODULO; +- pll_cs_dce110->registers[0].crtcx_pixel_rate_cntl = +- mmCRTC0_PIXEL_RATE_CNTL; +- +- break; +- +- default: +- ASSERT_CRITICAL(false); +- goto failure; +- } +- +- ss_info_from_atombios_create(pll_cs_dce110); +- +- return true; +- +-failure: +- destruct(pll_cs_dce110); +- +- return false; +-} +- +-struct clock_source *dal_pll_clock_source_dce110_create( +- struct clock_source_init_data *clk_src_init_data) +-{ +- struct pll_clock_source_dce110 *clk_src = +- dc_service_alloc(clk_src_init_data->ctx, sizeof(struct pll_clock_source_dce110)); +- +- if (clk_src == NULL) +- return NULL; +- +- if (!construct(clk_src, clk_src_init_data)) { +- dc_service_free(clk_src_init_data->ctx, clk_src); +- return NULL; +- } +- return &(clk_src->base.base); +-} +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.h +deleted file mode 100644 +index 166b29a..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/pll_clock_source_dce110.h ++++ /dev/null +@@ -1,55 +0,0 @@ +-/* Copyright 2012-15 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 __DAL_PLL_CLOCK_SOURCE_DCE110_H__ +-#define __DAL_PLL_CLOCK_SOURCE_DCE110_H__ +- +-#include "../pll_clock_source.h" +-#include "../calc_pll_clock_source.h" +- +-struct pll_clock_source_dce110 { +- struct pll_clock_source base; +- +- struct calc_pll_clock_source calc_pll_clock_source; +-/* object for normal circumstances, SS = 0 or SS >= 0.2% (LVDS or DP) +- * or even for SS =~0.02 (DVI) */ +- +- struct calc_pll_clock_source calc_pll_clock_source_hdmi; +-/* object for HDMI no SS or SS <= 0.06% */ +- +- struct registers *registers; +- +- uint32_t pixclkx_resync_cntl; +- uint32_t ppll_fb_div; +- uint32_t ppll_ref_div; +- uint32_t ppll_post_div; +- uint32_t pxpll_ds_cntl; +- uint32_t pxpll_ss_cntl; +- uint32_t pxpll_ss_dsfrac; +- uint32_t pxpll_cntl; +-}; +- +-struct clock_source *dal_pll_clock_source_dce110_create( +- struct clock_source_init_data *clk_src_init_data); +- +-#endif /*__DAL_PLL_CLOCK_SOURCE_DCE110__*/ +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.c b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.c +deleted file mode 100644 +index 249720f..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.c ++++ /dev/null +@@ -1,193 +0,0 @@ +-/* Copyright 2012-15 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 "dc_services.h" +-#include "vce_clock_source_dce110.h" +-#include "include/clock_source_types.h" +-#include "include/bios_parser_interface.h" +-#include "include/logger_interface.h" +- +-struct vce_clock_source_dce110 { +- struct clock_source base; +- uint32_t ref_freq_khz; +-}; +- +-static uint32_t get_pix_clk_dividers( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings) +-{ +- struct vce_clock_source_dce110 *vce_clk_src_dce110 = +- container_of( +- clk_src, +- struct vce_clock_source_dce110, +- base); +- if (pix_clk_params == NULL || +- pll_settings == NULL || +- pix_clk_params->requested_pix_clk == 0) { +- dal_logger_write(clk_src->ctx->logger, +- LOG_MAJOR_ERROR, +- LOG_MINOR_COMPONENT_GPU, +- "%s: Invalid parameters!!", __func__); +- return MAX_PLL_CALC_ERROR; +- } +- +- dc_service_memset(pll_settings, 0, sizeof(struct pll_settings)); +- pll_settings->reference_freq = vce_clk_src_dce110->ref_freq_khz; +- pll_settings->actual_pix_clk = +- pix_clk_params->requested_pix_clk; +- pll_settings->adjusted_pix_clk = +- pix_clk_params->requested_pix_clk; +- pll_settings->calculated_pix_clk = +- pix_clk_params->requested_pix_clk; +- +- return 0; +-} +-static bool program_pix_clk(struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings) +-{ +- struct bp_pixel_clock_parameters bp_pix_clk_params = { 0 }; +- +- if (pll_settings->actual_pix_clk == 0) +- return false; +- /* this is SimNow for Nutmeg*/ +- +- bp_pix_clk_params.controller_id = pix_clk_params->controller_id; +- bp_pix_clk_params.pll_id = clk_src->clk_src_id; +- bp_pix_clk_params.target_pixel_clock = pll_settings->actual_pix_clk; +- bp_pix_clk_params.encoder_object_id = pix_clk_params->encoder_object_id; +- bp_pix_clk_params.signal_type = pix_clk_params->signal_type; +- +- if (clk_src->bios_parser->funcs->set_pixel_clock(clk_src->bios_parser, +- &bp_pix_clk_params) == BP_RESULT_OK) +- return true; +- +- return false; +-} +- +-static bool power_down_pll(struct clock_source *clk_src, +- enum controller_id controller_id) +-{ +- return true; +-} +- +-static void destruct( +- struct vce_clock_source_dce110 *vce_clk_src) +-{ +- +-} +- +-static void destroy( +- struct clock_source **clk_src) +-{ +- struct vce_clock_source_dce110 *vce_clk_src; +- +- vce_clk_src = +- container_of(*clk_src, struct vce_clock_source_dce110, base); +- +- destruct(vce_clk_src); +- dc_service_free((*clk_src)->ctx, vce_clk_src); +- +- *clk_src = NULL; +-} +- +-static const struct clock_source_impl funcs = { +- .program_pix_clk = program_pix_clk, +- .adjust_pll_pixel_rate = dal_clock_source_base_adjust_pll_pixel_rate, +- .adjust_dto_pixel_rate = dal_clock_source_base_adjust_dto_pix_rate, +- .retrieve_pll_pix_rate_hz = +- dal_clock_source_base_retrieve_pll_pix_rate_hz, +- .get_pix_clk_dividers = get_pix_clk_dividers, +- .destroy = destroy, +- .retrieve_dto_pix_rate_hz = +- dal_clock_source_base_retrieve_dto_pix_rate_hz, +- .power_down_pll = power_down_pll, +-}; +- +-static bool construct( +- struct vce_clock_source_dce110 *vce_clk_src, +- struct clock_source_init_data *clk_src_init_data) +-{ +- struct firmware_info fw_info = { { 0 } }; +- +- if (!dal_clock_source_construct( +- &vce_clk_src->base, clk_src_init_data)) { +- ASSERT_CRITICAL(false); +- return false; +- } +- +- if (vce_clk_src->base.clk_src_id != CLOCK_SOURCE_ID_VCE) { +- dal_logger_write(clk_src_init_data->ctx->logger, +- LOG_MAJOR_ERROR, +- LOG_MINOR_COMPONENT_GPU, +- "Invalid ClockSourceId = %d!\n", +- vce_clk_src->base.clk_src_id); +- ASSERT_CRITICAL(false); +- dal_logger_write(clk_src_init_data->ctx->logger, +- LOG_MAJOR_ERROR, +- LOG_MINOR_COMPONENT_GPU, +- "Failed to create DCE110VceClockSource.\n"); +- return false; +- } +- +- vce_clk_src->base.funcs = &funcs; +- vce_clk_src->base.clk_sharing_lvl = CLOCK_SHARING_LEVEL_NOT_SHAREABLE; +- vce_clk_src->base.is_clock_source_with_fixed_freq = false; +- +- +- /*VCE clock source only supports SignalType_Wireless*/ +- vce_clk_src->base.output_signals |= SIGNAL_TYPE_WIRELESS; +- +- /*Get Reference frequency, Input frequency range into PLL +- * and Output frequency range of the PLL +- * from ATOMBIOS Data table */ +- if (vce_clk_src->base.bios_parser->funcs->get_firmware_info( +- vce_clk_src->base.bios_parser, +- &fw_info) != BP_RESULT_OK) +- return false; +- +- vce_clk_src->ref_freq_khz = fw_info.pll_info.crystal_frequency; +- +- return true; +-} +- +- +-struct clock_source *dal_vce_clock_source_dce110_create( +- struct clock_source_init_data *clk_src_init_data) +- +-{ +- struct vce_clock_source_dce110 *clk_src; +- +- clk_src = dc_service_alloc(clk_src_init_data->ctx, sizeof(struct vce_clock_source_dce110)); +- +- if (clk_src == NULL) +- return NULL; +- +- if (!construct(clk_src, clk_src_init_data)) { +- dc_service_free(clk_src_init_data->ctx, clk_src); +- return NULL; +- } +- +- return &clk_src->base; +-} +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.h b/drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.h +deleted file mode 100644 +index 227b169..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/dce110/vce_clock_source_dce110.h ++++ /dev/null +@@ -1,32 +0,0 @@ +-/* Copyright 2012-15 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 __DAL_VCE_CLOCK_SOURCE_DCE110__ +-#define __DAL_VCE_CLOCK_SOURCE_DCE110__ +- +-#include "../clock_source.h" +- +-struct clock_source *dal_vce_clock_source_dce110_create( +- struct clock_source_init_data *clk_src_init_data); +- +-#endif /*__DAL_VCE_CLOCK_SOURCE_DCE110__*/ +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.c b/drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.c +deleted file mode 100644 +index ec5b17d..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.c ++++ /dev/null +@@ -1,121 +0,0 @@ +-/* Copyright 2012-15 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 "dc_services.h" +- +-#include "include/bios_parser_interface.h" +-#include "include/clock_source_types.h" +-#include "include/logger_interface.h" +-#include "ext_clock_source.h" +- +-uint32_t dal_ext_clock_source_get_pix_clk_dividers( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings) +-{ +- struct ext_clock_source *ext_clk_src = container_of( +- clk_src, +- struct ext_clock_source, +- base); +- +- if (pix_clk_params == NULL || +- pll_settings == NULL || +- pix_clk_params->requested_pix_clk == 0) { +- dal_logger_write(clk_src->ctx->logger, +- LOG_MAJOR_WARNING, +- LOG_MINOR_COMPONENT_GPU, +- "%s: Invalid parameters!!", __func__); +- return MAX_PLL_CALC_ERROR; +- } +- +- dc_service_memset(pll_settings, 0, sizeof(struct pll_settings)); +- pll_settings->adjusted_pix_clk = ext_clk_src->ext_clk_freq_khz; +- pll_settings->calculated_pix_clk = ext_clk_src->ext_clk_freq_khz; +- pll_settings->actual_pix_clk = +- pix_clk_params->requested_pix_clk; +- return 0; +-} +- +-bool dal_ext_clock_source_program_pix_clk( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings) +-{ +- struct bp_pixel_clock_parameters bp_pix_clk_params = {0}; +- +- bp_pix_clk_params.controller_id = pix_clk_params->controller_id; +- bp_pix_clk_params.pll_id = clk_src->clk_src_id; +- bp_pix_clk_params.target_pixel_clock = +- pix_clk_params->requested_pix_clk; +- bp_pix_clk_params.encoder_object_id = pix_clk_params->encoder_object_id; +- bp_pix_clk_params.signal_type = pix_clk_params->signal_type; +- +- if (clk_src->bios_parser->funcs->set_pixel_clock( +- clk_src->bios_parser, +- &bp_pix_clk_params) == BP_RESULT_OK) +- return true; +- +- return false; +- +-} +- +-bool dal_ext_clock_source_power_down_pll(struct clock_source *clk_src, +- enum controller_id controller_id) +-{ +- return true; +-} +- +-bool dal_ext_clock_source_construct( +- struct ext_clock_source *ext_clk_src, +- struct clock_source_init_data *clk_src_init_data) +-{ +- struct firmware_info fw_info = { { 0 } }; +- +- if (!dal_clock_source_construct( +- &ext_clk_src->base, clk_src_init_data)) { +- BREAK_TO_DEBUGGER(); +- return false; +- } +- +- ext_clk_src->base.clk_sharing_lvl = +- CLOCK_SHARING_LEVEL_DISPLAY_PORT_SHAREABLE; +- ext_clk_src->base.is_clock_source_with_fixed_freq = true; +- /* ExtClock has fixed frequency, +- * so it supports only DisplayPort signals.*/ +- ext_clk_src->base.output_signals = +- SIGNAL_TYPE_DISPLAY_PORT | +- SIGNAL_TYPE_DISPLAY_PORT_MST | +- SIGNAL_TYPE_EDP; +- +- +- /*Get External clock frequency from ATOMBIOS Data table */ +- if (ext_clk_src->base.bios_parser->funcs->get_firmware_info( +- ext_clk_src->base.bios_parser, +- &fw_info) != BP_RESULT_OK) +- return false; +- +- ext_clk_src->ext_clk_freq_khz = fw_info. +- external_clock_source_frequency_for_dp; +- return true; +-} +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.h b/drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.h +deleted file mode 100644 +index bef1dc4..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/ext_clock_source.h ++++ /dev/null +@@ -1,47 +0,0 @@ +-/* Copyright 2012-15 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 __DAL_EXT_CLOCK_SOURCE_H__ +-#define __DAL_EXT_CLOCK_SOURCE_H__ +- +-#include "clock_source.h" +- +-struct ext_clock_source { +- struct clock_source base; +- uint32_t ext_clk_freq_khz; +-}; +- +-bool dal_ext_clock_source_construct( +- struct ext_clock_source *ext_cs, +- struct clock_source_init_data *clk_src_init_data); +-bool dal_ext_clock_source_power_down_pll(struct clock_source *clk_src, +- enum controller_id controller_id); +-uint32_t dal_ext_clock_source_get_pix_clk_dividers( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings); +-bool dal_ext_clock_source_program_pix_clk( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings); +-#endif /*__DAL_EXT_CLOCK_SOURCE_H__*/ +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.c b/drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.c +deleted file mode 100644 +index d00bb61..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.c ++++ /dev/null +@@ -1,139 +0,0 @@ +-/* Copyright 2012-15 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 "dc_services.h" +-#include "include/bios_parser_interface.h" +-#include "pll_clock_source.h" +- +-bool dal_pll_clock_source_power_down_pll( +- struct clock_source *clk_src, +- enum controller_id controller_id) +-{ +- +- enum bp_result bp_result; +- struct bp_pixel_clock_parameters bp_pixel_clock_params = {0}; +- +- /* If Pixel Clock is 0 it means Power Down Pll*/ +- bp_pixel_clock_params.controller_id = controller_id; +- bp_pixel_clock_params.pll_id = clk_src->clk_src_id; +- bp_pixel_clock_params.flags.FORCE_PROGRAMMING_OF_PLL = 1; +- +- /*Call ASICControl to process ATOMBIOS Exec table*/ +- bp_result = clk_src->bios_parser->funcs->set_pixel_clock( +- clk_src->bios_parser, +- &bp_pixel_clock_params); +- +- return bp_result == BP_RESULT_OK; +-} +- +-bool dal_pll_clock_source_adjust_pix_clk( +- struct pll_clock_source *pll_clk_src, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings) +-{ +- uint32_t actual_pix_clk_khz = 0; +- uint32_t requested_clk_khz = 0; +- struct bp_adjust_pixel_clock_parameters bp_adjust_pixel_clock_params = { +- 0 }; +- enum bp_result bp_result; +- +- switch (pix_clk_params->signal_type) { +- case SIGNAL_TYPE_HDMI_TYPE_A: { +- requested_clk_khz = pix_clk_params->requested_pix_clk; +- +- switch (pix_clk_params->color_depth) { +- case COLOR_DEPTH_101010: +- requested_clk_khz = (requested_clk_khz * 5) >> 2; +- break; /* x1.25*/ +- case COLOR_DEPTH_121212: +- requested_clk_khz = (requested_clk_khz * 6) >> 2; +- break; /* x1.5*/ +- case COLOR_DEPTH_161616: +- requested_clk_khz = requested_clk_khz * 2; +- break; /* x2.0*/ +- default: +- break; +- } +- +- actual_pix_clk_khz = requested_clk_khz; +- } +- break; +- +- case SIGNAL_TYPE_DISPLAY_PORT: +- case SIGNAL_TYPE_DISPLAY_PORT_MST: +- case SIGNAL_TYPE_EDP: +- requested_clk_khz = pix_clk_params->requested_sym_clk; +- actual_pix_clk_khz = pix_clk_params->requested_pix_clk; +- break; +- +- default: +- requested_clk_khz = pix_clk_params->requested_pix_clk; +- actual_pix_clk_khz = pix_clk_params->requested_pix_clk; +- break; +- } +- +- bp_adjust_pixel_clock_params.pixel_clock = requested_clk_khz; +- bp_adjust_pixel_clock_params. +- encoder_object_id = pix_clk_params->encoder_object_id; +- bp_adjust_pixel_clock_params.signal_type = pix_clk_params->signal_type; +- bp_adjust_pixel_clock_params. +- ss_enable = pix_clk_params->flags.ENABLE_SS; +- bp_result = pll_clk_src->base.bios_parser->funcs->adjust_pixel_clock( +- pll_clk_src->base.bios_parser, +- &bp_adjust_pixel_clock_params); +- if (bp_result == BP_RESULT_OK) { +- pll_settings->actual_pix_clk = actual_pix_clk_khz; +- pll_settings->adjusted_pix_clk = +- bp_adjust_pixel_clock_params.adjusted_pixel_clock; +- pll_settings->reference_divider = +- bp_adjust_pixel_clock_params.reference_divider; +- pll_settings->pix_clk_post_divider = +- bp_adjust_pixel_clock_params.pixel_clock_post_divider; +- +- return true; +- } +- +- return false; +-} +- +-bool dal_pll_clock_source_construct( +- struct pll_clock_source *pll_clk_src, +- struct clock_source_init_data *clk_src_init_data) +-{ +- struct firmware_info fw_info = { { 0 } }; +- +- if (!dal_clock_source_construct( +- &pll_clk_src->base, +- clk_src_init_data)) +- return false; +- +- if (pll_clk_src->base.bios_parser->funcs->get_firmware_info( +- pll_clk_src->base.bios_parser, +- &fw_info) != BP_RESULT_OK) +- return false; +- +- pll_clk_src->ref_freq_khz = fw_info.pll_info.crystal_frequency; +- +- return true; +-} +diff --git a/drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.h b/drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.h +deleted file mode 100644 +index 8339e1f..0000000 +--- a/drivers/gpu/drm/amd/dal/dc/gpu/pll_clock_source.h ++++ /dev/null +@@ -1,52 +0,0 @@ +-/* Copyright 2012-15 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 __DAL_PLL_CLOCK_SOURCE_H__ +-#define __DAL_PLL_CLOCK_SOURCE_H__ +- +-#include "gpu/clock_source.h" +- +-struct pll_clock_source { +- struct clock_source base; +- uint32_t ref_freq_khz; +-}; +- +-struct delta_sigma_data { +- uint32_t feedback_amount; +- uint32_t nfrac_amount; +- uint32_t ds_frac_size; +- uint32_t ds_frac_amount; +-}; +- +-bool dal_pll_clock_source_construct( +- struct pll_clock_source *pll_clk_src, +- struct clock_source_init_data *clk_src_init_data); +- +-bool dal_pll_clock_source_adjust_pix_clk( +- struct pll_clock_source *pll_clk_src, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings); +-bool dal_pll_clock_source_power_down_pll( +- struct clock_source *clk_src, +- enum controller_id controller_id); +-#endif /*__DAL_PLL_CLOCK_SOURCE_H__*/ +diff --git a/drivers/gpu/drm/amd/dal/dc/inc/clock_source.h b/drivers/gpu/drm/amd/dal/dc/inc/clock_source.h +new file mode 100644 +index 0000000..d7a9a0c +--- /dev/null ++++ b/drivers/gpu/drm/amd/dal/dc/inc/clock_source.h +@@ -0,0 +1,176 @@ ++/* ++ * Copyright 2012-15 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 __DC_CLOCK_SOURCE_H__ ++#define __DC_CLOCK_SOURCE_H__ ++ ++#include "dc_types.h" ++#include "include/grph_object_id.h" ++#include "include/bios_parser_types.h" ++ ++struct clock_source; ++ ++struct spread_spectrum_data { ++ uint32_t percentage; /*> In unit of 0.01% or 0.001%*/ ++ uint32_t percentage_divider; /*> 100 or 1000 */ ++ uint32_t freq_range_khz; ++ uint32_t modulation_freq_hz; ++ ++ struct spread_spectrum_flags flags; ++}; ++ ++struct delta_sigma_data { ++ uint32_t feedback_amount; ++ uint32_t nfrac_amount; ++ uint32_t ds_frac_size; ++ uint32_t ds_frac_amount; ++}; ++ ++/** ++ * Pixel Clock Parameters structure ++ * These parameters are required as input ++ * when calculating Pixel Clock Dividers for requested Pixel Clock ++ */ ++struct pixel_clk_flags { ++ uint32_t ENABLE_SS:1; ++ uint32_t DISPLAY_BLANKED:1; ++ uint32_t PROGRAM_PIXEL_CLOCK:1; ++ uint32_t PROGRAM_ID_CLOCK:1; ++}; ++ ++/** ++ * Display Port HW De spread of Reference Clock related Parameters structure ++ * Store it once at boot for later usage ++ */ ++struct csdp_ref_clk_ds_params { ++ bool hw_dso_n_dp_ref_clk; ++/* Flag for HW De Spread enabled (if enabled SS on DP Reference Clock)*/ ++ uint32_t avg_dp_ref_clk_khz; ++/* Average DP Reference clock (in KHz)*/ ++ uint32_t ss_percentage_on_dp_ref_clk; ++/* DP Reference clock SS percentage ++ * (not to be mixed with DP IDCLK SS from PLL Settings)*/ ++ uint32_t ss_percentage_divider; ++/* DP Reference clock SS percentage divider */ ++}; ++ ++struct pixel_clk_params { ++ uint32_t requested_pix_clk; /* in KHz */ ++/*> Requested Pixel Clock ++ * (based on Video Timing standard used for requested mode)*/ ++ uint32_t requested_sym_clk; /* in KHz */ ++/*> Requested Sym Clock (relevant only for display port)*/ ++ uint32_t dp_ref_clk; /* in KHz */ ++/*> DP reference clock - calculated only for DP signal for specific cases*/ ++ struct graphics_object_id encoder_object_id; ++/*> Encoder object Id - needed by VBIOS Exec table*/ ++ enum signal_type signal_type; ++/*> signalType -> Encoder Mode - needed by VBIOS Exec table*/ ++ enum controller_id controller_id; ++/*> ControllerId - which controller using this PLL*/ ++ enum dc_color_depth color_depth; ++ struct csdp_ref_clk_ds_params de_spread_params; ++/*> de-spread info, relevant only for on-the-fly tune-up pixel rate*/ ++ ++ struct pixel_clk_flags flags; ++}; ++ ++/** ++ * Pixel Clock Dividers structure with desired Pixel Clock ++ * (adjusted after VBIOS exec table), ++ * with actually calculated Clock and reference Crystal frequency ++ */ ++struct pll_settings { ++ uint32_t actual_pix_clk; ++ uint32_t adjusted_pix_clk; ++ uint32_t calculated_pix_clk; ++ uint32_t vco_freq; ++ uint32_t reference_freq; ++ uint32_t reference_divider; ++ uint32_t feedback_divider; ++ uint32_t fract_feedback_divider; ++ uint32_t pix_clk_post_divider; ++ uint32_t ss_percentage; ++ bool use_external_clk; ++}; ++ ++struct calc_pll_clock_source_init_data { ++ struct dc_bios *bp; ++ uint32_t min_pix_clk_pll_post_divider; ++ uint32_t max_pix_clk_pll_post_divider; ++ uint32_t min_pll_ref_divider; ++ uint32_t max_pll_ref_divider; ++ uint32_t min_override_input_pxl_clk_pll_freq_khz; ++/* if not 0, override the firmware info */ ++ ++ uint32_t max_override_input_pxl_clk_pll_freq_khz; ++/* if not 0, override the firmware info */ ++ ++ uint32_t num_fract_fb_divider_decimal_point; ++/* number of decimal point for fractional feedback divider value */ ++ ++ uint32_t num_fract_fb_divider_decimal_point_precision; ++/* number of decimal point to round off for fractional feedback divider value*/ ++ struct dc_context *ctx; ++ ++}; ++ ++struct calc_pll_clock_source { ++ uint32_t ref_freq_khz; ++ uint32_t min_pix_clock_pll_post_divider; ++ uint32_t max_pix_clock_pll_post_divider; ++ uint32_t min_pll_ref_divider; ++ uint32_t max_pll_ref_divider; ++ ++ uint32_t max_vco_khz; ++ uint32_t min_vco_khz; ++ uint32_t min_pll_input_freq_khz; ++ uint32_t max_pll_input_freq_khz; ++ ++ uint32_t fract_fb_divider_decimal_points_num; ++ uint32_t fract_fb_divider_factor; ++ uint32_t fract_fb_divider_precision; ++ uint32_t fract_fb_divider_precision_factor; ++ struct dc_context *ctx; ++}; ++ ++struct clock_source_funcs { ++ bool (*cs_power_down)( ++ struct clock_source *, enum controller_id); ++ bool (*program_pix_clk)(struct clock_source *, ++ struct pixel_clk_params *, struct pll_settings *); ++ uint32_t (*get_pix_clk_dividers)( ++ struct clock_source *, ++ struct pixel_clk_params *, ++ struct pll_settings *); ++}; ++ ++struct clock_source { ++ struct clock_source_funcs *funcs; ++ struct dc_context *ctx; ++ enum clock_source_id id; ++}; ++ ++#endif +diff --git a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h +index 8282f99..d075de1 100644 +--- a/drivers/gpu/drm/amd/dal/dc/inc/core_types.h ++++ b/drivers/gpu/drm/amd/dal/dc/inc/core_types.h +@@ -66,7 +66,7 @@ void enable_surface_flip_reporting(struct dc_surface *dc_surface, + #include "grph_object_id.h" + #include "link_encoder.h" + #include "stream_encoder.h" +-#include "clock_source_interface.h" ++#include "clock_source.h" + #include "audio_interface.h" + #include "scaler_types.h" + #include "hw_sequencer_types.h" +diff --git a/drivers/gpu/drm/amd/dal/include/bios_parser_types.h b/drivers/gpu/drm/amd/dal/include/bios_parser_types.h +index 6f72e25..6791866 100644 +--- a/drivers/gpu/drm/amd/dal/include/bios_parser_types.h ++++ b/drivers/gpu/drm/amd/dal/include/bios_parser_types.h +@@ -26,6 +26,7 @@ + #ifndef __DAL_BIOS_PARSER_TYPES_H__ + #define __DAL_BIOS_PARSER_TYPES_H__ + ++#include "dc_services.h" + #include "include/signal_types.h" + #include "include/grph_object_ctrl_defs.h" + #include "include/gpio_types.h" +diff --git a/drivers/gpu/drm/amd/dal/include/clock_source_interface.h b/drivers/gpu/drm/amd/dal/include/clock_source_interface.h +deleted file mode 100644 +index bea4c2b..0000000 +--- a/drivers/gpu/drm/amd/dal/include/clock_source_interface.h ++++ /dev/null +@@ -1,89 +0,0 @@ +-/* +- * Copyright 2012-15 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 __DAL_CLOCK_SOURCE_INTERFACE__ +-#define __DAL_CLOCK_SOURCE_INTERFACE__ +- +-#include "include/clock_source_types.h" +- +-struct clock_source; +-struct clock_source_init_data { +- struct adapter_service *as; +- struct graphics_object_id clk_src_id; +- struct dc_context *ctx; +-}; +- +-struct clock_source *dal_clock_source_create(struct clock_source_init_data *); +- +-void dal_clock_source_destroy(struct clock_source **clk_src); +- +-enum clock_source_id dal_clock_source_get_id( +- const struct clock_source *clk_src); +- +-bool dal_clock_source_is_clk_src_with_fixed_freq( +- const struct clock_source *clk_src); +- +-const struct graphics_object_id dal_clock_source_get_graphics_object_id( +- const struct clock_source *clk_src); +- +-enum clock_sharing_level dal_clock_souce_get_clk_sharing_lvl( +- const struct clock_source *clk_src); +- +-uint32_t dal_clock_source_get_pix_clk_dividers( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings); +- +-bool dal_clock_source_program_pix_clk( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- struct pll_settings *pll_settings); +- +-bool dal_clock_source_adjust_pxl_clk_by_ref_pixel_rate( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- uint32_t pix_clk_hz); +- +-bool dal_clock_source_adjust_pxl_clk_by_pix_amount( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params, +- int32_t pix_num); +- +-uint32_t dal_clock_source_retreive_pix_rate_hz( +- struct clock_source *clk_src, +- struct pixel_clk_params *pix_clk_params); +- +-bool dal_clock_source_power_down_pll(struct clock_source *clk_src, +- enum controller_id); +- +-bool dal_clock_source_is_clk_in_reset(struct clock_source *clk_src); +- +-bool dal_clock_source_is_gen_lock_capable(struct clock_source *clk_src); +- +-bool dal_clock_source_is_output_signal_supported( +- const struct clock_source *clk_src, +- enum signal_type signal_type); +- +-#endif /*__DAL_CLOCK_SOURCE_INTERFACE__*/ +diff --git a/drivers/gpu/drm/amd/dal/include/clock_source_types.h b/drivers/gpu/drm/amd/dal/include/clock_source_types.h +deleted file mode 100644 +index 4c323a9..0000000 +--- a/drivers/gpu/drm/amd/dal/include/clock_source_types.h ++++ /dev/null +@@ -1,113 +0,0 @@ +-/* +- * Copyright 2012-15 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 __DAL_CLOCK_SOURCE_TYPES_H__ +-#define __DAL_CLOCK_SOURCE_TYPES_H__ +- +-#include "include/signal_types.h" +-#include "include/grph_object_ctrl_defs.h" +- +-/** +- * ClockSharingLevel +- * Enumeration for clock sharing support. +- * Level <x> means sharing supported on all levels below and including <x> +- */ +-enum clock_sharing_level { +- CLOCK_SHARING_LEVEL_NOT_SHAREABLE = 0, +- CLOCK_SHARING_LEVEL_DP_MST_SHAREABLE, +- CLOCK_SHARING_LEVEL_DISPLAY_PORT_SHAREABLE +-}; +- +-/** +- * Display Port HW De spread of Reference Clock related Parameters structure +- * Store it once at boot for later usage +- */ +-struct csdp_ref_clk_ds_params { +- bool hw_dso_n_dp_ref_clk; +-/* Flag for HW De Spread enabled (if enabled SS on DP Reference Clock)*/ +- uint32_t avg_dp_ref_clk_khz; +-/* Average DP Reference clock (in KHz)*/ +- uint32_t ss_percentage_on_dp_ref_clk; +-/* DP Reference clock SS percentage +- * (not to be mixed with DP IDCLK SS from PLL Settings)*/ +- uint32_t ss_percentage_divider; +-/* DP Reference clock SS percentage divider */ +-}; +- +-/** +- * Pixel Clock Parameters structure +- * These parameters are required as input +- * when calculating Pixel Clock Dividers for requested Pixel Clock +- */ +-struct pixel_clk_flags { +- uint32_t ENABLE_SS:1; +- uint32_t DISPLAY_BLANKED:1; +- uint32_t PROGRAM_PIXEL_CLOCK:1; +- uint32_t PROGRAM_ID_CLOCK:1; +-}; +- +-struct pixel_clk_params { +- uint32_t requested_pix_clk; /* in KHz */ +-/*> Requested Pixel Clock +- * (based on Video Timing standard used for requested mode)*/ +- uint32_t requested_sym_clk; /* in KHz */ +-/*> Requested Sym Clock (relevant only for display port)*/ +- uint32_t dp_ref_clk; /* in KHz */ +-/*> DP reference clock - calculated only for DP signal for specific cases*/ +- struct graphics_object_id encoder_object_id; +-/*> Encoder object Id - needed by VBIOS Exec table*/ +- enum signal_type signal_type; +-/*> signalType -> Encoder Mode - needed by VBIOS Exec table*/ +- enum controller_id controller_id; +-/*> ControllerId - which controller using this PLL*/ +- enum dc_color_depth color_depth; +- struct csdp_ref_clk_ds_params de_spread_params; +-/*> de-spread info, relevant only for on-the-fly tune-up pixel rate*/ +- +- struct pixel_clk_flags flags; +-}; +- +-/** +- * Pixel Clock Dividers structure with desired Pixel Clock +- * (adjusted after VBIOS exec table), +- * with actually calculated Clock and reference Crystal frequency +- */ +-struct pll_settings { +- uint32_t actual_pix_clk; +- uint32_t adjusted_pix_clk; +- uint32_t calculated_pix_clk; +- uint32_t vco_freq; +- uint32_t reference_freq; +- uint32_t reference_divider; +- uint32_t feedback_divider; +- uint32_t fract_feedback_divider; +- uint32_t pix_clk_post_divider; +- uint32_t ss_percentage; +- bool use_external_clk; +-}; +- +-#define MAX_PLL_CALC_ERROR 0xFFFFFFFF +- +-#endif +-- +2.7.4 + |