From 6034b9e9fce49448ae2b0cdbd6b33ca2e46d222d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Mon, 25 Jan 2016 16:21:37 -0500 Subject: [PATCH 1304/1565] drm/amd/dal: refactor clock sources Change-Id: I321b9dc3723d814906ef7e3603e1701ae7bf7da4 Signed-off-by: Dmytro Laktyushkin Acked-by: Harry Wentland --- 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 means sharing supported on all levels below and including - */ -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 -- 1.9.1