brintos

brintos / linux-shallow public Read only

0
0
Text · 58.3 KiB · b700608 Raw
1870 lines · c
1/*2 * Copyright 2012-15 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26#include "dm_services.h"27 28 29#include "dc_types.h"30#include "core_types.h"31 32#include "include/grph_object_id.h"33#include "include/logger_interface.h"34 35#include "dce_clock_source.h"36#include "clk_mgr.h"37#include "dccg.h"38 39#include "reg_helper.h"40 41#define REG(reg)\42	(clk_src->regs->reg)43 44#define CTX \45	clk_src->base.ctx46 47#define DC_LOGGER \48	calc_pll_cs->ctx->logger49#define DC_LOGGER_INIT() \50	struct calc_pll_clock_source *calc_pll_cs = &clk_src->calc_pll51 52#undef FN53#define FN(reg_name, field_name) \54	clk_src->cs_shift->field_name, clk_src->cs_mask->field_name55 56#define FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM 657#define CALC_PLL_CLK_SRC_ERR_TOLERANCE 158#define MAX_PLL_CALC_ERROR 0xFFFFFFFF59 60#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))61 62static const struct spread_spectrum_data *get_ss_data_entry(63		struct dce110_clk_src *clk_src,64		enum signal_type signal,65		uint32_t pix_clk_khz)66{67 68	uint32_t entrys_num;69	uint32_t i;70	struct spread_spectrum_data *ss_parm = NULL;71	struct spread_spectrum_data *ret = NULL;72 73	switch (signal) {74	case SIGNAL_TYPE_DVI_SINGLE_LINK:75	case SIGNAL_TYPE_DVI_DUAL_LINK:76		ss_parm = clk_src->dvi_ss_params;77		entrys_num = clk_src->dvi_ss_params_cnt;78		break;79 80	case SIGNAL_TYPE_HDMI_TYPE_A:81		ss_parm = clk_src->hdmi_ss_params;82		entrys_num = clk_src->hdmi_ss_params_cnt;83		break;84 85	case SIGNAL_TYPE_LVDS:86		ss_parm = clk_src->lvds_ss_params;87		entrys_num = clk_src->lvds_ss_params_cnt;88		break;89 90	case SIGNAL_TYPE_DISPLAY_PORT:91	case SIGNAL_TYPE_DISPLAY_PORT_MST:92	case SIGNAL_TYPE_EDP:93	case SIGNAL_TYPE_VIRTUAL:94		ss_parm = clk_src->dp_ss_params;95		entrys_num = clk_src->dp_ss_params_cnt;96		break;97 98	default:99		ss_parm = NULL;100		entrys_num = 0;101		break;102	}103 104	if (ss_parm == NULL)105		return ret;106 107	for (i = 0; i < entrys_num; ++i, ++ss_parm) {108		if (ss_parm->freq_range_khz >= pix_clk_khz) {109			ret = ss_parm;110			break;111		}112	}113 114	return ret;115}116 117/**118 * calculate_fb_and_fractional_fb_divider - Calculates feedback and fractional119 *                                          feedback dividers values120 *121 * @calc_pll_cs:	    Pointer to clock source information122 * @target_pix_clk_100hz:   Desired frequency in 100 Hz123 * @ref_divider:            Reference divider (already known)124 * @post_divider:           Post Divider (already known)125 * @feedback_divider_param: Pointer where to store126 *			    calculated feedback divider value127 * @fract_feedback_divider_param: Pointer where to store128 *			    calculated fract feedback divider value129 *130 * return:131 * It fills the locations pointed by feedback_divider_param132 *					and fract_feedback_divider_param133 * It returns	- true if feedback divider not 0134 *		- false should never happen)135 */136static bool calculate_fb_and_fractional_fb_divider(137		struct calc_pll_clock_source *calc_pll_cs,138		uint32_t target_pix_clk_100hz,139		uint32_t ref_divider,140		uint32_t post_divider,141		uint32_t *feedback_divider_param,142		uint32_t *fract_feedback_divider_param)143{144	uint64_t feedback_divider;145 146	feedback_divider =147		(uint64_t)target_pix_clk_100hz * ref_divider * post_divider;148	feedback_divider *= 10;149	/* additional factor, since we divide by 10 afterwards */150	feedback_divider *= (uint64_t)(calc_pll_cs->fract_fb_divider_factor);151	feedback_divider = div_u64(feedback_divider, calc_pll_cs->ref_freq_khz * 10ull);152 153/*Round to the number of precision154 * The following code replace the old code (ullfeedbackDivider + 5)/10155 * for example if the difference between the number156 * of fractional feedback decimal point and the fractional FB Divider precision157 * is 2 then the equation becomes (ullfeedbackDivider + 5*100) / (10*100))*/158 159	feedback_divider += 5ULL *160			    calc_pll_cs->fract_fb_divider_precision_factor;161	feedback_divider =162		div_u64(feedback_divider,163			calc_pll_cs->fract_fb_divider_precision_factor * 10);164	feedback_divider *= (uint64_t)165			(calc_pll_cs->fract_fb_divider_precision_factor);166 167	*feedback_divider_param =168		div_u64_rem(169			feedback_divider,170			calc_pll_cs->fract_fb_divider_factor,171			fract_feedback_divider_param);172 173	if (*feedback_divider_param != 0)174		return true;175	return false;176}177 178/**179 * calc_fb_divider_checking_tolerance - Calculates Feedback and180 *                                      Fractional Feedback divider values181 *		                        for passed Reference and Post divider,182 *                                      checking for tolerance.183 * @calc_pll_cs:	Pointer to clock source information184 * @pll_settings:	Pointer to PLL settings185 * @ref_divider:	Reference divider (already known)186 * @post_divider:	Post Divider (already known)187 * @tolerance:		Tolerance for Calculated Pixel Clock to be within188 *189 * return:190 *  It fills the PLLSettings structure with PLL Dividers values191 *  if calculated values are within required tolerance192 *  It returns	- true if error is within tolerance193 *		- false if error is not within tolerance194 */195static bool calc_fb_divider_checking_tolerance(196		struct calc_pll_clock_source *calc_pll_cs,197		struct pll_settings *pll_settings,198		uint32_t ref_divider,199		uint32_t post_divider,200		uint32_t tolerance)201{202	uint32_t feedback_divider;203	uint32_t fract_feedback_divider;204	uint32_t actual_calculated_clock_100hz;205	uint32_t abs_err;206	uint64_t actual_calc_clk_100hz;207 208	calculate_fb_and_fractional_fb_divider(209			calc_pll_cs,210			pll_settings->adjusted_pix_clk_100hz,211			ref_divider,212			post_divider,213			&feedback_divider,214			&fract_feedback_divider);215 216	/*Actual calculated value*/217	actual_calc_clk_100hz = (uint64_t)feedback_divider *218					calc_pll_cs->fract_fb_divider_factor +219							fract_feedback_divider;220	actual_calc_clk_100hz *= (uint64_t)calc_pll_cs->ref_freq_khz * 10;221	actual_calc_clk_100hz =222		div_u64(actual_calc_clk_100hz,223			ref_divider * post_divider *224				calc_pll_cs->fract_fb_divider_factor);225 226	actual_calculated_clock_100hz = (uint32_t)(actual_calc_clk_100hz);227 228	abs_err = (actual_calculated_clock_100hz >229					pll_settings->adjusted_pix_clk_100hz)230			? actual_calculated_clock_100hz -231					pll_settings->adjusted_pix_clk_100hz232			: pll_settings->adjusted_pix_clk_100hz -233						actual_calculated_clock_100hz;234 235	if (abs_err <= tolerance) {236		/*found good values*/237		pll_settings->reference_freq = calc_pll_cs->ref_freq_khz;238		pll_settings->reference_divider = ref_divider;239		pll_settings->feedback_divider = feedback_divider;240		pll_settings->fract_feedback_divider = fract_feedback_divider;241		pll_settings->pix_clk_post_divider = post_divider;242		pll_settings->calculated_pix_clk_100hz =243			actual_calculated_clock_100hz;244		pll_settings->vco_freq =245			div_u64((u64)actual_calculated_clock_100hz * post_divider, 10);246		return true;247	}248	return false;249}250 251static bool calc_pll_dividers_in_range(252		struct calc_pll_clock_source *calc_pll_cs,253		struct pll_settings *pll_settings,254		uint32_t min_ref_divider,255		uint32_t max_ref_divider,256		uint32_t min_post_divider,257		uint32_t max_post_divider,258		uint32_t err_tolerance)259{260	uint32_t ref_divider;261	uint32_t post_divider;262	uint32_t tolerance;263 264/* This is err_tolerance / 10000 = 0.0025 - acceptable error of 0.25%265 * This is errorTolerance / 10000 = 0.0001 - acceptable error of 0.01%*/266	tolerance = (pll_settings->adjusted_pix_clk_100hz * err_tolerance) /267									100000;268	if (tolerance < CALC_PLL_CLK_SRC_ERR_TOLERANCE)269		tolerance = CALC_PLL_CLK_SRC_ERR_TOLERANCE;270 271	for (272			post_divider = max_post_divider;273			post_divider >= min_post_divider;274			--post_divider) {275		for (276				ref_divider = min_ref_divider;277				ref_divider <= max_ref_divider;278				++ref_divider) {279			if (calc_fb_divider_checking_tolerance(280					calc_pll_cs,281					pll_settings,282					ref_divider,283					post_divider,284					tolerance)) {285				return true;286			}287		}288	}289 290	return false;291}292 293static uint32_t calculate_pixel_clock_pll_dividers(294		struct calc_pll_clock_source *calc_pll_cs,295		struct pll_settings *pll_settings)296{297	uint32_t err_tolerance;298	uint32_t min_post_divider;299	uint32_t max_post_divider;300	uint32_t min_ref_divider;301	uint32_t max_ref_divider;302 303	if (pll_settings->adjusted_pix_clk_100hz == 0) {304		DC_LOG_ERROR(305			"%s Bad requested pixel clock", __func__);306		return MAX_PLL_CALC_ERROR;307	}308 309/* 1) Find Post divider ranges */310	if (pll_settings->pix_clk_post_divider) {311		min_post_divider = pll_settings->pix_clk_post_divider;312		max_post_divider = pll_settings->pix_clk_post_divider;313	} else {314		min_post_divider = calc_pll_cs->min_pix_clock_pll_post_divider;315		if (min_post_divider * pll_settings->adjusted_pix_clk_100hz <316						calc_pll_cs->min_vco_khz * 10) {317			min_post_divider = calc_pll_cs->min_vco_khz * 10 /318					pll_settings->adjusted_pix_clk_100hz;319			if ((min_post_divider *320					pll_settings->adjusted_pix_clk_100hz) <321						calc_pll_cs->min_vco_khz * 10)322				min_post_divider++;323		}324 325		max_post_divider = calc_pll_cs->max_pix_clock_pll_post_divider;326		if (max_post_divider * pll_settings->adjusted_pix_clk_100hz327				> calc_pll_cs->max_vco_khz * 10)328			max_post_divider = calc_pll_cs->max_vco_khz * 10 /329					pll_settings->adjusted_pix_clk_100hz;330	}331 332/* 2) Find Reference divider ranges333 * When SS is enabled, or for Display Port even without SS,334 * pll_settings->referenceDivider is not zero.335 * So calculate PPLL FB and fractional FB divider336 * using the passed reference divider*/337 338	if (pll_settings->reference_divider) {339		min_ref_divider = pll_settings->reference_divider;340		max_ref_divider = pll_settings->reference_divider;341	} else {342		min_ref_divider = ((calc_pll_cs->ref_freq_khz343				/ calc_pll_cs->max_pll_input_freq_khz)344				> calc_pll_cs->min_pll_ref_divider)345			? calc_pll_cs->ref_freq_khz346					/ calc_pll_cs->max_pll_input_freq_khz347			: calc_pll_cs->min_pll_ref_divider;348 349		max_ref_divider = ((calc_pll_cs->ref_freq_khz350				/ calc_pll_cs->min_pll_input_freq_khz)351				< calc_pll_cs->max_pll_ref_divider)352			? calc_pll_cs->ref_freq_khz /353					calc_pll_cs->min_pll_input_freq_khz354			: calc_pll_cs->max_pll_ref_divider;355	}356 357/* If some parameters are invalid we could have scenario when  "min">"max"358 * which produced endless loop later.359 * We should investigate why we get the wrong parameters.360 * But to follow the similar logic when "adjustedPixelClock" is set to be 0361 * it is better to return here than cause system hang/watchdog timeout later.362 *  ## SVS Wed 15 Jul 2009 */363 364	if (min_post_divider > max_post_divider) {365		DC_LOG_ERROR(366			"%s Post divider range is invalid", __func__);367		return MAX_PLL_CALC_ERROR;368	}369 370	if (min_ref_divider > max_ref_divider) {371		DC_LOG_ERROR(372			"%s Reference divider range is invalid", __func__);373		return MAX_PLL_CALC_ERROR;374	}375 376/* 3) Try to find PLL dividers given ranges377 * starting with minimal error tolerance.378 * Increase error tolerance until PLL dividers found*/379	err_tolerance = MAX_PLL_CALC_ERROR;380 381	while (!calc_pll_dividers_in_range(382			calc_pll_cs,383			pll_settings,384			min_ref_divider,385			max_ref_divider,386			min_post_divider,387			max_post_divider,388			err_tolerance))389		err_tolerance += (err_tolerance > 10)390				? (err_tolerance / 10)391				: 1;392 393	return err_tolerance;394}395 396static bool pll_adjust_pix_clk(397		struct dce110_clk_src *clk_src,398		struct pixel_clk_params *pix_clk_params,399		struct pll_settings *pll_settings)400{401	uint32_t actual_pix_clk_100hz = 0;402	uint32_t requested_clk_100hz = 0;403	struct bp_adjust_pixel_clock_parameters bp_adjust_pixel_clock_params = {404							0 };405	enum bp_result bp_result;406	switch (pix_clk_params->signal_type) {407	case SIGNAL_TYPE_HDMI_TYPE_A: {408		requested_clk_100hz = pix_clk_params->requested_pix_clk_100hz;409		if (pix_clk_params->pixel_encoding != PIXEL_ENCODING_YCBCR422) {410			switch (pix_clk_params->color_depth) {411			case COLOR_DEPTH_101010:412				requested_clk_100hz = (requested_clk_100hz * 5) >> 2;413				break; /* x1.25*/414			case COLOR_DEPTH_121212:415				requested_clk_100hz = (requested_clk_100hz * 6) >> 2;416				break; /* x1.5*/417			case COLOR_DEPTH_161616:418				requested_clk_100hz = requested_clk_100hz * 2;419				break; /* x2.0*/420			default:421				break;422			}423		}424		actual_pix_clk_100hz = requested_clk_100hz;425	}426		break;427 428	case SIGNAL_TYPE_DISPLAY_PORT:429	case SIGNAL_TYPE_DISPLAY_PORT_MST:430	case SIGNAL_TYPE_EDP:431		requested_clk_100hz = pix_clk_params->requested_sym_clk * 10;432		actual_pix_clk_100hz = pix_clk_params->requested_pix_clk_100hz;433		break;434 435	default:436		requested_clk_100hz = pix_clk_params->requested_pix_clk_100hz;437		actual_pix_clk_100hz = pix_clk_params->requested_pix_clk_100hz;438		break;439	}440 441	bp_adjust_pixel_clock_params.pixel_clock = requested_clk_100hz / 10;442	bp_adjust_pixel_clock_params.443		encoder_object_id = pix_clk_params->encoder_object_id;444	bp_adjust_pixel_clock_params.signal_type = pix_clk_params->signal_type;445	bp_adjust_pixel_clock_params.446		ss_enable = pix_clk_params->flags.ENABLE_SS;447	bp_result = clk_src->bios->funcs->adjust_pixel_clock(448			clk_src->bios, &bp_adjust_pixel_clock_params);449	if (bp_result == BP_RESULT_OK) {450		pll_settings->actual_pix_clk_100hz = actual_pix_clk_100hz;451		pll_settings->adjusted_pix_clk_100hz =452			bp_adjust_pixel_clock_params.adjusted_pixel_clock * 10;453		pll_settings->reference_divider =454			bp_adjust_pixel_clock_params.reference_divider;455		pll_settings->pix_clk_post_divider =456			bp_adjust_pixel_clock_params.pixel_clock_post_divider;457 458		return true;459	}460 461	return false;462}463 464/*465 * Calculate PLL Dividers for given Clock Value.466 * First will call VBIOS Adjust Exec table to check if requested Pixel clock467 * will be Adjusted based on usage.468 * Then it will calculate PLL Dividers for this Adjusted clock using preferred469 * method (Maximum VCO frequency).470 *471 * \return472 *     Calculation error in units of 0.01%473 */474 475static uint32_t dce110_get_pix_clk_dividers_helper (476		struct dce110_clk_src *clk_src,477		struct pll_settings *pll_settings,478		struct pixel_clk_params *pix_clk_params)479{480	uint32_t field = 0;481	uint32_t pll_calc_error = MAX_PLL_CALC_ERROR;482	DC_LOGGER_INIT();483	/* Check if reference clock is external (not pcie/xtalin)484	* HW Dce80 spec:485	* 00 - PCIE_REFCLK, 01 - XTALIN,    02 - GENERICA,    03 - GENERICB486	* 04 - HSYNCA,      05 - GENLK_CLK, 06 - PCIE_REFCLK, 07 - DVOCLK0 */487	REG_GET(PLL_CNTL, PLL_REF_DIV_SRC, &field);488	pll_settings->use_external_clk = (field > 1);489 490	/* VBIOS by default enables DP SS (spread on IDCLK) for DCE 8.0 always491	 * (we do not care any more from SI for some older DP Sink which492	 * does not report SS support, no known issues) */493	if ((pix_clk_params->flags.ENABLE_SS) ||494			(dc_is_dp_signal(pix_clk_params->signal_type))) {495 496		const struct spread_spectrum_data *ss_data = get_ss_data_entry(497					clk_src,498					pix_clk_params->signal_type,499					pll_settings->adjusted_pix_clk_100hz / 10);500 501		if (NULL != ss_data)502			pll_settings->ss_percentage = ss_data->percentage;503	}504 505	/* Check VBIOS AdjustPixelClock Exec table */506	if (!pll_adjust_pix_clk(clk_src, pix_clk_params, pll_settings)) {507		/* Should never happen, ASSERT and fill up values to be able508		 * to continue. */509		DC_LOG_ERROR(510			"%s: Failed to adjust pixel clock!!", __func__);511		pll_settings->actual_pix_clk_100hz =512				pix_clk_params->requested_pix_clk_100hz;513		pll_settings->adjusted_pix_clk_100hz =514				pix_clk_params->requested_pix_clk_100hz;515 516		if (dc_is_dp_signal(pix_clk_params->signal_type))517			pll_settings->adjusted_pix_clk_100hz = 1000000;518	}519 520	/* Calculate Dividers */521	if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A)522		/*Calculate Dividers by HDMI object, no SS case or SS case */523		pll_calc_error =524			calculate_pixel_clock_pll_dividers(525					&clk_src->calc_pll_hdmi,526					pll_settings);527	else528		/*Calculate Dividers by default object, no SS case or SS case */529		pll_calc_error =530			calculate_pixel_clock_pll_dividers(531					&clk_src->calc_pll,532					pll_settings);533 534	return pll_calc_error;535}536 537static void dce112_get_pix_clk_dividers_helper (538		struct dce110_clk_src *clk_src,539		struct pll_settings *pll_settings,540		struct pixel_clk_params *pix_clk_params)541{542	uint32_t actual_pixel_clock_100hz;543 544	actual_pixel_clock_100hz = pix_clk_params->requested_pix_clk_100hz;545	/* Calculate Dividers */546	if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) {547		switch (pix_clk_params->color_depth) {548		case COLOR_DEPTH_101010:549			actual_pixel_clock_100hz = (actual_pixel_clock_100hz * 5) >> 2;550			actual_pixel_clock_100hz -= actual_pixel_clock_100hz % 10;551			break;552		case COLOR_DEPTH_121212:553			actual_pixel_clock_100hz = (actual_pixel_clock_100hz * 6) >> 2;554			actual_pixel_clock_100hz -= actual_pixel_clock_100hz % 10;555			break;556		case COLOR_DEPTH_161616:557			actual_pixel_clock_100hz = actual_pixel_clock_100hz * 2;558			break;559		default:560			break;561		}562	}563	pll_settings->actual_pix_clk_100hz = actual_pixel_clock_100hz;564	pll_settings->adjusted_pix_clk_100hz = actual_pixel_clock_100hz;565	pll_settings->calculated_pix_clk_100hz = pix_clk_params->requested_pix_clk_100hz;566}567 568static uint32_t dce110_get_pix_clk_dividers(569		struct clock_source *cs,570		struct pixel_clk_params *pix_clk_params,571		struct pll_settings *pll_settings)572{573	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(cs);574	uint32_t pll_calc_error = MAX_PLL_CALC_ERROR;575	DC_LOGGER_INIT();576 577	if (pix_clk_params == NULL || pll_settings == NULL578			|| pix_clk_params->requested_pix_clk_100hz == 0) {579		DC_LOG_ERROR(580			"%s: Invalid parameters!!\n", __func__);581		return pll_calc_error;582	}583 584	memset(pll_settings, 0, sizeof(*pll_settings));585 586	if (cs->id == CLOCK_SOURCE_ID_DP_DTO ||587			cs->id == CLOCK_SOURCE_ID_EXTERNAL) {588		pll_settings->adjusted_pix_clk_100hz = clk_src->ext_clk_khz * 10;589		pll_settings->calculated_pix_clk_100hz = clk_src->ext_clk_khz * 10;590		pll_settings->actual_pix_clk_100hz =591					pix_clk_params->requested_pix_clk_100hz;592		return 0;593	}594 595	pll_calc_error = dce110_get_pix_clk_dividers_helper(clk_src,596			pll_settings, pix_clk_params);597 598	return pll_calc_error;599}600 601static uint32_t dce112_get_pix_clk_dividers(602		struct clock_source *cs,603		struct pixel_clk_params *pix_clk_params,604		struct pll_settings *pll_settings)605{606	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(cs);607	DC_LOGGER_INIT();608 609	if (pix_clk_params == NULL || pll_settings == NULL610			|| pix_clk_params->requested_pix_clk_100hz == 0) {611		DC_LOG_ERROR(612			"%s: Invalid parameters!!\n", __func__);613		return -1;614	}615 616	memset(pll_settings, 0, sizeof(*pll_settings));617 618	if (cs->id == CLOCK_SOURCE_ID_DP_DTO ||619			cs->id == CLOCK_SOURCE_ID_EXTERNAL) {620		pll_settings->adjusted_pix_clk_100hz = clk_src->ext_clk_khz * 10;621		pll_settings->calculated_pix_clk_100hz = clk_src->ext_clk_khz * 10;622		pll_settings->actual_pix_clk_100hz =623					pix_clk_params->requested_pix_clk_100hz;624		return -1;625	}626 627	dce112_get_pix_clk_dividers_helper(clk_src,628			pll_settings, pix_clk_params);629 630	return 0;631}632 633static bool disable_spread_spectrum(struct dce110_clk_src *clk_src)634{635	enum bp_result result;636	struct bp_spread_spectrum_parameters bp_ss_params = {0};637 638	bp_ss_params.pll_id = clk_src->base.id;639 640	/*Call ASICControl to process ATOMBIOS Exec table*/641	result = clk_src->bios->funcs->enable_spread_spectrum_on_ppll(642			clk_src->bios,643			&bp_ss_params,644			false);645 646	return result == BP_RESULT_OK;647}648 649static bool calculate_ss(650		const struct pll_settings *pll_settings,651		const struct spread_spectrum_data *ss_data,652		struct delta_sigma_data *ds_data)653{654	struct fixed31_32 fb_div;655	struct fixed31_32 ss_amount;656	struct fixed31_32 ss_nslip_amount;657	struct fixed31_32 ss_ds_frac_amount;658	struct fixed31_32 ss_step_size;659	struct fixed31_32 modulation_time;660 661	if (ds_data == NULL)662		return false;663	if (ss_data == NULL)664		return false;665	if (ss_data->percentage == 0)666		return false;667	if (pll_settings == NULL)668		return false;669 670	memset(ds_data, 0, sizeof(struct delta_sigma_data));671 672	/* compute SS_AMOUNT_FBDIV & SS_AMOUNT_NFRAC_SLIP & SS_AMOUNT_DSFRAC*/673	/* 6 decimal point support in fractional feedback divider */674	fb_div  = dc_fixpt_from_fraction(675		pll_settings->fract_feedback_divider, 1000000);676	fb_div = dc_fixpt_add_int(fb_div, pll_settings->feedback_divider);677 678	ds_data->ds_frac_amount = 0;679	/*spreadSpectrumPercentage is in the unit of .01%,680	 * so have to divided by 100 * 100*/681	ss_amount = dc_fixpt_mul(682		fb_div, dc_fixpt_from_fraction(ss_data->percentage,683					100 * (long long)ss_data->percentage_divider));684	ds_data->feedback_amount = dc_fixpt_floor(ss_amount);685 686	ss_nslip_amount = dc_fixpt_sub(ss_amount,687		dc_fixpt_from_int(ds_data->feedback_amount));688	ss_nslip_amount = dc_fixpt_mul_int(ss_nslip_amount, 10);689	ds_data->nfrac_amount = dc_fixpt_floor(ss_nslip_amount);690 691	ss_ds_frac_amount = dc_fixpt_sub(ss_nslip_amount,692		dc_fixpt_from_int(ds_data->nfrac_amount));693	ss_ds_frac_amount = dc_fixpt_mul_int(ss_ds_frac_amount, 65536);694	ds_data->ds_frac_amount = dc_fixpt_floor(ss_ds_frac_amount);695 696	/* compute SS_STEP_SIZE_DSFRAC */697	modulation_time = dc_fixpt_from_fraction(698		pll_settings->reference_freq * (uint64_t)1000,699		pll_settings->reference_divider * (uint64_t)ss_data->modulation_freq_hz);700 701	if (ss_data->flags.CENTER_SPREAD)702		modulation_time = dc_fixpt_div_int(modulation_time, 4);703	else704		modulation_time = dc_fixpt_div_int(modulation_time, 2);705 706	ss_step_size = dc_fixpt_div(ss_amount, modulation_time);707	/* SS_STEP_SIZE_DSFRAC_DEC = Int(SS_STEP_SIZE * 2 ^ 16 * 10)*/708	ss_step_size = dc_fixpt_mul_int(ss_step_size, 65536 * 10);709	ds_data->ds_frac_size =  dc_fixpt_floor(ss_step_size);710 711	return true;712}713 714static bool enable_spread_spectrum(715		struct dce110_clk_src *clk_src,716		enum signal_type signal, struct pll_settings *pll_settings)717{718	struct bp_spread_spectrum_parameters bp_params = {0};719	struct delta_sigma_data d_s_data;720	const struct spread_spectrum_data *ss_data = NULL;721 722	ss_data = get_ss_data_entry(723			clk_src,724			signal,725			pll_settings->calculated_pix_clk_100hz / 10);726 727/* Pixel clock PLL has been programmed to generate desired pixel clock,728 * now enable SS on pixel clock */729/* TODO is it OK to return true not doing anything ??*/730	if (ss_data != NULL && pll_settings->ss_percentage != 0) {731		if (calculate_ss(pll_settings, ss_data, &d_s_data)) {732			bp_params.ds.feedback_amount =733					d_s_data.feedback_amount;734			bp_params.ds.nfrac_amount =735					d_s_data.nfrac_amount;736			bp_params.ds.ds_frac_size = d_s_data.ds_frac_size;737			bp_params.ds_frac_amount =738					d_s_data.ds_frac_amount;739			bp_params.flags.DS_TYPE = 1;740			bp_params.pll_id = clk_src->base.id;741			bp_params.percentage = ss_data->percentage;742			if (ss_data->flags.CENTER_SPREAD)743				bp_params.flags.CENTER_SPREAD = 1;744			if (ss_data->flags.EXTERNAL_SS)745				bp_params.flags.EXTERNAL_SS = 1;746 747			if (BP_RESULT_OK !=748				clk_src->bios->funcs->749					enable_spread_spectrum_on_ppll(750							clk_src->bios,751							&bp_params,752							true))753				return false;754		} else755			return false;756	}757	return true;758}759 760static void dce110_program_pixel_clk_resync(761		struct dce110_clk_src *clk_src,762		enum signal_type signal_type,763		enum dc_color_depth colordepth)764{765	REG_UPDATE(RESYNC_CNTL,766			DCCG_DEEP_COLOR_CNTL1, 0);767	/*768	 24 bit mode: TMDS clock = 1.0 x pixel clock  (1:1)769	 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4)770	 36 bit mode: TMDS clock = 1.5 x pixel clock  (3:2)771	 48 bit mode: TMDS clock = 2 x pixel clock    (2:1)772	 */773	if (signal_type != SIGNAL_TYPE_HDMI_TYPE_A)774		return;775 776	switch (colordepth) {777	case COLOR_DEPTH_888:778		REG_UPDATE(RESYNC_CNTL,779				DCCG_DEEP_COLOR_CNTL1, 0);780		break;781	case COLOR_DEPTH_101010:782		REG_UPDATE(RESYNC_CNTL,783				DCCG_DEEP_COLOR_CNTL1, 1);784		break;785	case COLOR_DEPTH_121212:786		REG_UPDATE(RESYNC_CNTL,787				DCCG_DEEP_COLOR_CNTL1, 2);788		break;789	case COLOR_DEPTH_161616:790		REG_UPDATE(RESYNC_CNTL,791				DCCG_DEEP_COLOR_CNTL1, 3);792		break;793	default:794		break;795	}796}797 798static void dce112_program_pixel_clk_resync(799		struct dce110_clk_src *clk_src,800		enum signal_type signal_type,801		enum dc_color_depth colordepth,802		bool enable_ycbcr420)803{804	uint32_t deep_color_cntl = 0;805	uint32_t double_rate_enable = 0;806 807	/*808	 24 bit mode: TMDS clock = 1.0 x pixel clock  (1:1)809	 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4)810	 36 bit mode: TMDS clock = 1.5 x pixel clock  (3:2)811	 48 bit mode: TMDS clock = 2 x pixel clock    (2:1)812	 */813	if (signal_type == SIGNAL_TYPE_HDMI_TYPE_A) {814		double_rate_enable = enable_ycbcr420 ? 1 : 0;815 816		switch (colordepth) {817		case COLOR_DEPTH_888:818			deep_color_cntl = 0;819			break;820		case COLOR_DEPTH_101010:821			deep_color_cntl = 1;822			break;823		case COLOR_DEPTH_121212:824			deep_color_cntl = 2;825			break;826		case COLOR_DEPTH_161616:827			deep_color_cntl = 3;828			break;829		default:830			break;831		}832	}833 834	if (clk_src->cs_mask->PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE)835		REG_UPDATE_2(PIXCLK_RESYNC_CNTL,836				PHYPLLA_DCCG_DEEP_COLOR_CNTL, deep_color_cntl,837				PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, double_rate_enable);838	else839		REG_UPDATE(PIXCLK_RESYNC_CNTL,840				PHYPLLA_DCCG_DEEP_COLOR_CNTL, deep_color_cntl);841 842}843 844static bool dce110_program_pix_clk(845		struct clock_source *clock_source,846		struct pixel_clk_params *pix_clk_params,847		enum dp_link_encoding encoding,848		struct pll_settings *pll_settings)849{850	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);851	struct bp_pixel_clock_parameters bp_pc_params = {0};852 853	/* First disable SS854	 * ATOMBIOS will enable by default SS on PLL for DP,855	 * do not disable it here856	 */857	if (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL &&858			!dc_is_dp_signal(pix_clk_params->signal_type) &&859			clock_source->ctx->dce_version <= DCE_VERSION_11_0)860		disable_spread_spectrum(clk_src);861 862	/*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/863	bp_pc_params.controller_id = pix_clk_params->controller_id;864	bp_pc_params.pll_id = clock_source->id;865	bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz;866	bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id;867	bp_pc_params.signal_type = pix_clk_params->signal_type;868 869	bp_pc_params.reference_divider = pll_settings->reference_divider;870	bp_pc_params.feedback_divider = pll_settings->feedback_divider;871	bp_pc_params.fractional_feedback_divider =872			pll_settings->fract_feedback_divider;873	bp_pc_params.pixel_clock_post_divider =874			pll_settings->pix_clk_post_divider;875	bp_pc_params.flags.SET_EXTERNAL_REF_DIV_SRC =876					pll_settings->use_external_clk;877 878	switch (pix_clk_params->color_depth) {879	case COLOR_DEPTH_101010:880		bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_30;881		break;882	case COLOR_DEPTH_121212:883		bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_36;884		break;885	case COLOR_DEPTH_161616:886		bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_48;887		break;888	default:889		break;890	}891 892	if (clk_src->bios->funcs->set_pixel_clock(893			clk_src->bios, &bp_pc_params) != BP_RESULT_OK)894		return false;895	/* Enable SS896	 * ATOMBIOS will enable by default SS for DP on PLL ( DP ID clock),897	 * based on HW display PLL team, SS control settings should be programmed898	 * during PLL Reset, but they do not have effect899	 * until SS_EN is asserted.*/900	if (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL901			&& !dc_is_dp_signal(pix_clk_params->signal_type)) {902 903		if (pix_clk_params->flags.ENABLE_SS)904			if (!enable_spread_spectrum(clk_src,905							pix_clk_params->signal_type,906							pll_settings))907				return false;908 909		/* Resync deep color DTO */910		dce110_program_pixel_clk_resync(clk_src,911					pix_clk_params->signal_type,912					pix_clk_params->color_depth);913	}914 915	return true;916}917 918static bool dce112_program_pix_clk(919		struct clock_source *clock_source,920		struct pixel_clk_params *pix_clk_params,921		enum dp_link_encoding encoding,922		struct pll_settings *pll_settings)923{924	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);925	struct bp_pixel_clock_parameters bp_pc_params = {0};926 927	/* First disable SS928	 * ATOMBIOS will enable by default SS on PLL for DP,929	 * do not disable it here930	 */931	if (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL &&932			!dc_is_dp_signal(pix_clk_params->signal_type) &&933			clock_source->ctx->dce_version <= DCE_VERSION_11_0)934		disable_spread_spectrum(clk_src);935 936	/*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/937	bp_pc_params.controller_id = pix_clk_params->controller_id;938	bp_pc_params.pll_id = clock_source->id;939	bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz;940	bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id;941	bp_pc_params.signal_type = pix_clk_params->signal_type;942 943	if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {944		bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC =945						pll_settings->use_external_clk;946		bp_pc_params.flags.SET_XTALIN_REF_SRC =947						!pll_settings->use_external_clk;948		if (pix_clk_params->flags.SUPPORT_YCBCR420) {949			bp_pc_params.flags.SUPPORT_YUV_420 = 1;950		}951	}952	if (clk_src->bios->funcs->set_pixel_clock(953			clk_src->bios, &bp_pc_params) != BP_RESULT_OK)954		return false;955	/* Resync deep color DTO */956	if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO)957		dce112_program_pixel_clk_resync(clk_src,958					pix_clk_params->signal_type,959					pix_clk_params->color_depth,960					pix_clk_params->flags.SUPPORT_YCBCR420);961 962	return true;963}964 965static bool dcn31_program_pix_clk(966		struct clock_source *clock_source,967		struct pixel_clk_params *pix_clk_params,968		enum dp_link_encoding encoding,969		struct pll_settings *pll_settings)970{971	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);972	unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;973	unsigned int dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dprefclk_khz;974	const struct pixel_rate_range_table_entry *e =975			look_up_in_video_optimized_rate_tlb(pix_clk_params->requested_pix_clk_100hz / 10);976	struct bp_pixel_clock_parameters bp_pc_params = {0};977	enum transmitter_color_depth bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24;978 979	// Apply ssed(spread spectrum) dpref clock for edp only.980	if (clock_source->ctx->dc->clk_mgr->dp_dto_source_clock_in_khz != 0981		&& pix_clk_params->signal_type == SIGNAL_TYPE_EDP982		&& encoding == DP_8b_10b_ENCODING)983		dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dp_dto_source_clock_in_khz;984	// For these signal types Driver to program DP_DTO without calling VBIOS Command table985	if (dc_is_dp_signal(pix_clk_params->signal_type) || dc_is_virtual_signal(pix_clk_params->signal_type)) {986		if (e) {987			/* Set DTO values: phase = target clock, modulo = reference clock*/988			REG_WRITE(PHASE[inst], e->target_pixel_rate_khz * e->mult_factor);989			REG_WRITE(MODULO[inst], dp_dto_ref_khz * e->div_factor);990		} else {991			/* Set DTO values: phase = target clock, modulo = reference clock*/992			REG_WRITE(PHASE[inst], pll_settings->actual_pix_clk_100hz * 100);993			REG_WRITE(MODULO[inst], dp_dto_ref_khz * 1000);994		}995		/* Enable DTO */996		if (clk_src->cs_mask->PIPE0_DTO_SRC_SEL)997			if (encoding == DP_128b_132b_ENCODING)998				REG_UPDATE_2(PIXEL_RATE_CNTL[inst],999						DP_DTO0_ENABLE, 1,1000						PIPE0_DTO_SRC_SEL, 2);1001			else1002				REG_UPDATE_2(PIXEL_RATE_CNTL[inst],1003						DP_DTO0_ENABLE, 1,1004						PIPE0_DTO_SRC_SEL, 1);1005		else1006			REG_UPDATE(PIXEL_RATE_CNTL[inst],1007					DP_DTO0_ENABLE, 1);1008	} else {1009 1010		if (clk_src->cs_mask->PIPE0_DTO_SRC_SEL)1011			REG_UPDATE(PIXEL_RATE_CNTL[inst],1012					PIPE0_DTO_SRC_SEL, 0);1013 1014		/*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/1015		bp_pc_params.controller_id = pix_clk_params->controller_id;1016		bp_pc_params.pll_id = clock_source->id;1017		bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz;1018		bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id;1019		bp_pc_params.signal_type = pix_clk_params->signal_type;1020 1021		// Make sure we send the correct color depth to DMUB for HDMI1022		if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) {1023			switch (pix_clk_params->color_depth) {1024			case COLOR_DEPTH_888:1025				bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24;1026				break;1027			case COLOR_DEPTH_101010:1028				bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_30;1029				break;1030			case COLOR_DEPTH_121212:1031				bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_36;1032				break;1033			case COLOR_DEPTH_161616:1034				bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_48;1035				break;1036			default:1037				bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24;1038				break;1039			}1040			bp_pc_params.color_depth = bp_pc_colour_depth;1041		}1042 1043		if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {1044			bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC =1045							pll_settings->use_external_clk;1046			bp_pc_params.flags.SET_XTALIN_REF_SRC =1047							!pll_settings->use_external_clk;1048			if (pix_clk_params->flags.SUPPORT_YCBCR420) {1049				bp_pc_params.flags.SUPPORT_YUV_420 = 1;1050			}1051		}1052		if (clk_src->bios->funcs->set_pixel_clock(1053				clk_src->bios, &bp_pc_params) != BP_RESULT_OK)1054			return false;1055		/* Resync deep color DTO */1056		if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO)1057			dce112_program_pixel_clk_resync(clk_src,1058						pix_clk_params->signal_type,1059						pix_clk_params->color_depth,1060						pix_clk_params->flags.SUPPORT_YCBCR420);1061	}1062 1063	return true;1064}1065 1066static bool dcn401_program_pix_clk(1067		struct clock_source *clock_source,1068		struct pixel_clk_params *pix_clk_params,1069		enum dp_link_encoding encoding,1070		struct pll_settings *pll_settings)1071{1072	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);1073	unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;1074	const struct pixel_rate_range_table_entry *e =1075			look_up_in_video_optimized_rate_tlb(pix_clk_params->requested_pix_clk_100hz / 10);1076	struct bp_pixel_clock_parameters bp_pc_params = {0};1077	enum transmitter_color_depth bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24;1078	struct dp_dto_params dto_params = { 0 };1079 1080	dto_params.otg_inst = inst;1081	dto_params.signal = pix_clk_params->signal_type;1082 1083	// all but TMDS gets Driver to program DP_DTO without calling VBIOS Command table1084	if (!dc_is_tmds_signal(pix_clk_params->signal_type)) {1085		long long dtbclk_p_src_clk_khz;1086 1087		dtbclk_p_src_clk_khz = clock_source->ctx->dc->clk_mgr->dprefclk_khz;1088		dto_params.clk_src = DPREFCLK;1089 1090		if (e) {1091			dto_params.pixclk_hz = e->target_pixel_rate_khz;1092			dto_params.pixclk_hz *= e->mult_factor;1093			dto_params.refclk_hz = dtbclk_p_src_clk_khz;1094			dto_params.refclk_hz *= e->div_factor;1095		} else {1096			dto_params.pixclk_hz = pix_clk_params->requested_pix_clk_100hz;1097			dto_params.pixclk_hz *= 100;1098			dto_params.refclk_hz = dtbclk_p_src_clk_khz;1099			dto_params.refclk_hz *= 1000;1100		}1101 1102		/* enable DP DTO */1103		clock_source->ctx->dc->res_pool->dccg->funcs->set_dp_dto(1104				clock_source->ctx->dc->res_pool->dccg,1105				&dto_params);1106 1107	} else {1108		/* disables DP DTO when provided with TMDS signal type */1109		clock_source->ctx->dc->res_pool->dccg->funcs->set_dp_dto(1110				clock_source->ctx->dc->res_pool->dccg,1111				&dto_params);1112 1113		/*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/1114		bp_pc_params.controller_id = pix_clk_params->controller_id;1115		bp_pc_params.pll_id = clock_source->id;1116		bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz;1117		bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id;1118		bp_pc_params.signal_type = pix_clk_params->signal_type;1119 1120		// Make sure we send the correct color depth to DMUB for HDMI1121		if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) {1122			switch (pix_clk_params->color_depth) {1123			case COLOR_DEPTH_888:1124				bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24;1125				break;1126			case COLOR_DEPTH_101010:1127				bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_30;1128				break;1129			case COLOR_DEPTH_121212:1130				bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_36;1131				break;1132			case COLOR_DEPTH_161616:1133				bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_48;1134				break;1135			default:1136				bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24;1137				break;1138			}1139			bp_pc_params.color_depth = bp_pc_colour_depth;1140		}1141 1142		if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {1143			bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC =1144							pll_settings->use_external_clk;1145			bp_pc_params.flags.SET_XTALIN_REF_SRC =1146							!pll_settings->use_external_clk;1147			if (pix_clk_params->flags.SUPPORT_YCBCR420) {1148				bp_pc_params.flags.SUPPORT_YUV_420 = 1;1149			}1150		}1151		if (clk_src->bios->funcs->set_pixel_clock(1152				clk_src->bios, &bp_pc_params) != BP_RESULT_OK)1153			return false;1154		/* Resync deep color DTO */1155		if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO)1156			dce112_program_pixel_clk_resync(clk_src,1157						pix_clk_params->signal_type,1158						pix_clk_params->color_depth,1159						pix_clk_params->flags.SUPPORT_YCBCR420);1160	}1161 1162	return true;1163}1164 1165static bool dce110_clock_source_power_down(1166		struct clock_source *clk_src)1167{1168	struct dce110_clk_src *dce110_clk_src = TO_DCE110_CLK_SRC(clk_src);1169	enum bp_result bp_result;1170	struct bp_pixel_clock_parameters bp_pixel_clock_params = {0};1171 1172	if (clk_src->dp_clk_src)1173		return true;1174 1175	/* If Pixel Clock is 0 it means Power Down Pll*/1176	bp_pixel_clock_params.controller_id = CONTROLLER_ID_UNDEFINED;1177	bp_pixel_clock_params.pll_id = clk_src->id;1178	bp_pixel_clock_params.flags.FORCE_PROGRAMMING_OF_PLL = 1;1179 1180	/*Call ASICControl to process ATOMBIOS Exec table*/1181	bp_result = dce110_clk_src->bios->funcs->set_pixel_clock(1182			dce110_clk_src->bios,1183			&bp_pixel_clock_params);1184 1185	return bp_result == BP_RESULT_OK;1186}1187 1188static bool get_pixel_clk_frequency_100hz(1189		const struct clock_source *clock_source,1190		unsigned int inst,1191		unsigned int *pixel_clk_khz)1192{1193	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);1194	unsigned int clock_hz = 0;1195	unsigned int modulo_hz = 0;1196	unsigned int dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dprefclk_khz;1197 1198	if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) {1199		clock_hz = REG_READ(PHASE[inst]);1200 1201		if (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&1202			clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {1203			/* NOTE: In case VBLANK syncronization is enabled, MODULO may1204			 * not be programmed equal to DPREFCLK1205			 */1206			modulo_hz = REG_READ(MODULO[inst]);1207			if (modulo_hz)1208				*pixel_clk_khz = div_u64((uint64_t)clock_hz*1209					dp_dto_ref_khz*10,1210					modulo_hz);1211			else1212				*pixel_clk_khz = 0;1213		} else {1214			/* NOTE: There is agreement with VBIOS here that MODULO is1215			 * programmed equal to DPREFCLK, in which case PHASE will be1216			 * equivalent to pixel clock.1217			 */1218			*pixel_clk_khz = clock_hz / 100;1219		}1220		return true;1221	}1222 1223	return false;1224}1225 1226/* this table is use to find *1.001 and /1.001 pixel rates from non-precise pixel rate */1227const struct pixel_rate_range_table_entry video_optimized_pixel_rates[] = {1228	// /1.001 rates1229	{25170, 25180, 25200, 1000, 1001},	//25.2MHz   ->   25.171230	{59340, 59350, 59400, 1000, 1001},	//59.4Mhz   ->   59.3401231	{74170, 74180, 74250, 1000, 1001},	//74.25Mhz  ->   74.17581232	{89910, 90000, 90000, 1000, 1001},	//90Mhz     ->   89.911233	{125870, 125880, 126000, 1000, 1001},	//126Mhz    ->  125.871234	{148350, 148360, 148500, 1000, 1001},	//148.5Mhz  ->  148.35161235	{167830, 167840, 168000, 1000, 1001},	//168Mhz    ->  167.831236	{222520, 222530, 222750, 1000, 1001},	//222.75Mhz ->  222.5271237	{257140, 257150, 257400, 1000, 1001},	//257.4Mhz  ->  257.14291238	{296700, 296710, 297000, 1000, 1001},	//297Mhz    ->  296.70331239	{342850, 342860, 343200, 1000, 1001},	//343.2Mhz  ->  342.8571240	{395600, 395610, 396000, 1000, 1001},	//396Mhz    ->  395.61241	{409090, 409100, 409500, 1000, 1001},	//409.5Mhz  ->  409.0911242	{445050, 445060, 445500, 1000, 1001},	//445.5Mhz  ->  445.0551243	{467530, 467540, 468000, 1000, 1001},	//468Mhz    ->  467.53251244	{519230, 519240, 519750, 1000, 1001},	//519.75Mhz ->  519.2311245	{525970, 525980, 526500, 1000, 1001},	//526.5Mhz  ->  525.9741246	{545450, 545460, 546000, 1000, 1001},	//546Mhz    ->  545.4551247	{593400, 593410, 594000, 1000, 1001},	//594Mhz    ->  593.40661248	{623370, 623380, 624000, 1000, 1001},	//624Mhz    ->  623.3771249	{692300, 692310, 693000, 1000, 1001},	//693Mhz    ->  692.3081250	{701290, 701300, 702000, 1000, 1001},	//702Mhz    ->  701.29871251	{791200, 791210, 792000, 1000, 1001},	//792Mhz    ->  791.2091252	{890100, 890110, 891000, 1000, 1001},	//891Mhz    ->  890.10991253	{1186810, 1186820, 1188000, 1000, 1001},//1188Mhz   -> 1186.81311254 1255	// *1.001 rates1256	{27020, 27030, 27000, 1001, 1000}, //27Mhz1257	{54050, 54060, 54000, 1001, 1000}, //54Mhz1258	{108100, 108110, 108000, 1001, 1000},//108Mhz1259};1260 1261const struct pixel_rate_range_table_entry *look_up_in_video_optimized_rate_tlb(1262		unsigned int pixel_rate_khz)1263{1264	int i;1265 1266	for (i = 0; i < NUM_ELEMENTS(video_optimized_pixel_rates); i++) {1267		const struct pixel_rate_range_table_entry *e = &video_optimized_pixel_rates[i];1268 1269		if (e->range_min_khz <= pixel_rate_khz && pixel_rate_khz <= e->range_max_khz) {1270			return e;1271		}1272	}1273 1274	return NULL;1275}1276 1277static bool dcn20_program_pix_clk(1278		struct clock_source *clock_source,1279		struct pixel_clk_params *pix_clk_params,1280		enum dp_link_encoding encoding,1281		struct pll_settings *pll_settings)1282{1283	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);1284	unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;1285 1286	dce112_program_pix_clk(clock_source, pix_clk_params, encoding, pll_settings);1287 1288	if (clock_source->ctx->dc->hwss.enable_vblanks_synchronization &&1289			clock_source->ctx->dc->config.vblank_alignment_max_frame_time_diff > 0) {1290		/* NOTE: In case VBLANK syncronization is enabled,1291		 * we need to set modulo to default DPREFCLK first1292		 * dce112_program_pix_clk does not set default DPREFCLK1293		 */1294		REG_WRITE(MODULO[inst],1295			clock_source->ctx->dc->clk_mgr->dprefclk_khz*1000);1296	}1297	return true;1298}1299 1300static bool dcn20_override_dp_pix_clk(1301		struct clock_source *clock_source,1302		unsigned int inst,1303		unsigned int pixel_clk,1304		unsigned int ref_clk)1305{1306	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);1307 1308	REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 0);1309	REG_WRITE(PHASE[inst], pixel_clk);1310	REG_WRITE(MODULO[inst], ref_clk);1311	REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1);1312	return true;1313}1314 1315static const struct clock_source_funcs dcn20_clk_src_funcs = {1316	.cs_power_down = dce110_clock_source_power_down,1317	.program_pix_clk = dcn20_program_pix_clk,1318	.get_pix_clk_dividers = dce112_get_pix_clk_dividers,1319	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz,1320	.override_dp_pix_clk = dcn20_override_dp_pix_clk1321};1322 1323static bool dcn3_program_pix_clk(1324		struct clock_source *clock_source,1325		struct pixel_clk_params *pix_clk_params,1326		enum dp_link_encoding encoding,1327		struct pll_settings *pll_settings)1328{1329	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);1330	unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;1331	unsigned int dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dprefclk_khz;1332	const struct pixel_rate_range_table_entry *e =1333			look_up_in_video_optimized_rate_tlb(pix_clk_params->requested_pix_clk_100hz / 10);1334 1335	// For these signal types Driver to program DP_DTO without calling VBIOS Command table1336	if (dc_is_dp_signal(pix_clk_params->signal_type)) {1337		if (e) {1338			/* Set DTO values: phase = target clock, modulo = reference clock*/1339			REG_WRITE(PHASE[inst], e->target_pixel_rate_khz * e->mult_factor);1340			REG_WRITE(MODULO[inst], dp_dto_ref_khz * e->div_factor);1341		} else {1342			/* Set DTO values: phase = target clock, modulo = reference clock*/1343			REG_WRITE(PHASE[inst], pll_settings->actual_pix_clk_100hz * 100);1344			REG_WRITE(MODULO[inst], dp_dto_ref_khz * 1000);1345		}1346		/* Enable DTO */1347		if (clk_src->cs_mask->PIPE0_DTO_SRC_SEL)1348			REG_UPDATE_2(PIXEL_RATE_CNTL[inst],1349					DP_DTO0_ENABLE, 1,1350					PIPE0_DTO_SRC_SEL, 1);1351		else1352			REG_UPDATE(PIXEL_RATE_CNTL[inst],1353					DP_DTO0_ENABLE, 1);1354	} else1355		// For other signal types(HDMI_TYPE_A, DVI) Driver still to call VBIOS Command table1356		dce112_program_pix_clk(clock_source, pix_clk_params, encoding, pll_settings);1357 1358	return true;1359}1360 1361static uint32_t dcn3_get_pix_clk_dividers(1362		struct clock_source *cs,1363		struct pixel_clk_params *pix_clk_params,1364		struct pll_settings *pll_settings)1365{1366	unsigned long long actual_pix_clk_100Hz = pix_clk_params ? pix_clk_params->requested_pix_clk_100hz : 0;1367	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(cs);1368 1369	DC_LOGGER_INIT();1370 1371	if (pix_clk_params == NULL || pll_settings == NULL1372			|| pix_clk_params->requested_pix_clk_100hz == 0) {1373		DC_LOG_ERROR(1374			"%s: Invalid parameters!!\n", __func__);1375		return -1;1376	}1377 1378	memset(pll_settings, 0, sizeof(*pll_settings));1379	/* Adjust for HDMI Type A deep color */1380	if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) {1381		switch (pix_clk_params->color_depth) {1382		case COLOR_DEPTH_101010:1383			actual_pix_clk_100Hz = (actual_pix_clk_100Hz * 5) >> 2;1384			break;1385		case COLOR_DEPTH_121212:1386			actual_pix_clk_100Hz = (actual_pix_clk_100Hz * 6) >> 2;1387			break;1388		case COLOR_DEPTH_161616:1389			actual_pix_clk_100Hz = actual_pix_clk_100Hz * 2;1390			break;1391		default:1392			break;1393		}1394	}1395	pll_settings->actual_pix_clk_100hz = (unsigned int) actual_pix_clk_100Hz;1396	pll_settings->adjusted_pix_clk_100hz = (unsigned int) actual_pix_clk_100Hz;1397	pll_settings->calculated_pix_clk_100hz = (unsigned int) actual_pix_clk_100Hz;1398 1399	return 0;1400}1401 1402static const struct clock_source_funcs dcn3_clk_src_funcs = {1403	.cs_power_down = dce110_clock_source_power_down,1404	.program_pix_clk = dcn3_program_pix_clk,1405	.get_pix_clk_dividers = dcn3_get_pix_clk_dividers,1406	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz1407};1408 1409static const struct clock_source_funcs dcn31_clk_src_funcs = {1410	.cs_power_down = dce110_clock_source_power_down,1411	.program_pix_clk = dcn31_program_pix_clk,1412	.get_pix_clk_dividers = dcn3_get_pix_clk_dividers,1413	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz1414};1415 1416static const struct clock_source_funcs dcn401_clk_src_funcs = {1417	.cs_power_down = dce110_clock_source_power_down,1418	.program_pix_clk = dcn401_program_pix_clk,1419	.get_pix_clk_dividers = dcn3_get_pix_clk_dividers,1420	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz1421};1422 1423/*****************************************/1424/* Constructor                           */1425/*****************************************/1426 1427static const struct clock_source_funcs dce112_clk_src_funcs = {1428	.cs_power_down = dce110_clock_source_power_down,1429	.program_pix_clk = dce112_program_pix_clk,1430	.get_pix_clk_dividers = dce112_get_pix_clk_dividers,1431	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz1432};1433static const struct clock_source_funcs dce110_clk_src_funcs = {1434	.cs_power_down = dce110_clock_source_power_down,1435	.program_pix_clk = dce110_program_pix_clk,1436	.get_pix_clk_dividers = dce110_get_pix_clk_dividers,1437	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz1438};1439 1440 1441static void get_ss_info_from_atombios(1442		struct dce110_clk_src *clk_src,1443		enum as_signal_type as_signal,1444		struct spread_spectrum_data *spread_spectrum_data[],1445		uint32_t *ss_entries_num)1446{1447	enum bp_result bp_result = BP_RESULT_FAILURE;1448	struct spread_spectrum_info *ss_info;1449	struct spread_spectrum_data *ss_data;1450	struct spread_spectrum_info *ss_info_cur;1451	struct spread_spectrum_data *ss_data_cur;1452	uint32_t i;1453	DC_LOGGER_INIT();1454	if (ss_entries_num == NULL) {1455		DC_LOG_SYNC(1456			"Invalid entry !!!\n");1457		return;1458	}1459	if (spread_spectrum_data == NULL) {1460		DC_LOG_SYNC(1461			"Invalid array pointer!!!\n");1462		return;1463	}1464 1465	spread_spectrum_data[0] = NULL;1466	*ss_entries_num = 0;1467 1468	*ss_entries_num = clk_src->bios->funcs->get_ss_entry_number(1469			clk_src->bios,1470			as_signal);1471 1472	if (*ss_entries_num == 0)1473		return;1474 1475	ss_info = kcalloc(*ss_entries_num,1476			  sizeof(struct spread_spectrum_info),1477			  GFP_KERNEL);1478	ss_info_cur = ss_info;1479	if (ss_info == NULL)1480		return;1481 1482	ss_data = kcalloc(*ss_entries_num,1483			  sizeof(struct spread_spectrum_data),1484			  GFP_KERNEL);1485	if (ss_data == NULL)1486		goto out_free_info;1487 1488	for (i = 0, ss_info_cur = ss_info;1489		i < (*ss_entries_num);1490		++i, ++ss_info_cur) {1491 1492		bp_result = clk_src->bios->funcs->get_spread_spectrum_info(1493				clk_src->bios,1494				as_signal,1495				i,1496				ss_info_cur);1497 1498		if (bp_result != BP_RESULT_OK)1499			goto out_free_data;1500	}1501 1502	for (i = 0, ss_info_cur = ss_info, ss_data_cur = ss_data;1503		i < (*ss_entries_num);1504		++i, ++ss_info_cur, ++ss_data_cur) {1505 1506		if (ss_info_cur->type.STEP_AND_DELAY_INFO != false) {1507			DC_LOG_SYNC(1508				"Invalid ATOMBIOS SS Table!!!\n");1509			goto out_free_data;1510		}1511 1512		/* for HDMI check SS percentage,1513		 * if it is > 6 (0.06%), the ATOMBIOS table info is invalid*/1514		if (as_signal == AS_SIGNAL_TYPE_HDMI1515				&& ss_info_cur->spread_spectrum_percentage > 6){1516			/* invalid input, do nothing */1517			DC_LOG_SYNC(1518				"Invalid SS percentage ");1519			DC_LOG_SYNC(1520				"for HDMI in ATOMBIOS info Table!!!\n");1521			continue;1522		}1523		if (ss_info_cur->spread_percentage_divider == 1000) {1524			/* Keep previous precision from ATOMBIOS for these1525			* in case new precision set by ATOMBIOS for these1526			* (otherwise all code in DCE specific classes1527			* for all previous ASICs would need1528			* to be updated for SS calculations,1529			* Audio SS compensation and DP DTO SS compensation1530			* which assumes fixed SS percentage Divider = 100)*/1531			ss_info_cur->spread_spectrum_percentage /= 10;1532			ss_info_cur->spread_percentage_divider = 100;1533		}1534 1535		ss_data_cur->freq_range_khz = ss_info_cur->target_clock_range;1536		ss_data_cur->percentage =1537				ss_info_cur->spread_spectrum_percentage;1538		ss_data_cur->percentage_divider =1539				ss_info_cur->spread_percentage_divider;1540		ss_data_cur->modulation_freq_hz =1541				ss_info_cur->spread_spectrum_range;1542 1543		if (ss_info_cur->type.CENTER_MODE)1544			ss_data_cur->flags.CENTER_SPREAD = 1;1545 1546		if (ss_info_cur->type.EXTERNAL)1547			ss_data_cur->flags.EXTERNAL_SS = 1;1548 1549	}1550 1551	*spread_spectrum_data = ss_data;1552	kfree(ss_info);1553	return;1554 1555out_free_data:1556	kfree(ss_data);1557	*ss_entries_num = 0;1558out_free_info:1559	kfree(ss_info);1560}1561 1562static void ss_info_from_atombios_create(1563	struct dce110_clk_src *clk_src)1564{1565	get_ss_info_from_atombios(1566		clk_src,1567		AS_SIGNAL_TYPE_DISPLAY_PORT,1568		&clk_src->dp_ss_params,1569		&clk_src->dp_ss_params_cnt);1570	get_ss_info_from_atombios(1571		clk_src,1572		AS_SIGNAL_TYPE_HDMI,1573		&clk_src->hdmi_ss_params,1574		&clk_src->hdmi_ss_params_cnt);1575	get_ss_info_from_atombios(1576		clk_src,1577		AS_SIGNAL_TYPE_DVI,1578		&clk_src->dvi_ss_params,1579		&clk_src->dvi_ss_params_cnt);1580	get_ss_info_from_atombios(1581		clk_src,1582		AS_SIGNAL_TYPE_LVDS,1583		&clk_src->lvds_ss_params,1584		&clk_src->lvds_ss_params_cnt);1585}1586 1587static bool calc_pll_max_vco_construct(1588			struct calc_pll_clock_source *calc_pll_cs,1589			struct calc_pll_clock_source_init_data *init_data)1590{1591	uint32_t i;1592	struct dc_firmware_info *fw_info;1593	if (calc_pll_cs == NULL ||1594			init_data == NULL ||1595			init_data->bp == NULL)1596		return false;1597 1598	if (!init_data->bp->fw_info_valid)1599		return false;1600 1601	fw_info = &init_data->bp->fw_info;1602	calc_pll_cs->ctx = init_data->ctx;1603	calc_pll_cs->ref_freq_khz = fw_info->pll_info.crystal_frequency;1604	calc_pll_cs->min_vco_khz =1605			fw_info->pll_info.min_output_pxl_clk_pll_frequency;1606	calc_pll_cs->max_vco_khz =1607			fw_info->pll_info.max_output_pxl_clk_pll_frequency;1608 1609	if (init_data->max_override_input_pxl_clk_pll_freq_khz != 0)1610		calc_pll_cs->max_pll_input_freq_khz =1611			init_data->max_override_input_pxl_clk_pll_freq_khz;1612	else1613		calc_pll_cs->max_pll_input_freq_khz =1614			fw_info->pll_info.max_input_pxl_clk_pll_frequency;1615 1616	if (init_data->min_override_input_pxl_clk_pll_freq_khz != 0)1617		calc_pll_cs->min_pll_input_freq_khz =1618			init_data->min_override_input_pxl_clk_pll_freq_khz;1619	else1620		calc_pll_cs->min_pll_input_freq_khz =1621			fw_info->pll_info.min_input_pxl_clk_pll_frequency;1622 1623	calc_pll_cs->min_pix_clock_pll_post_divider =1624			init_data->min_pix_clk_pll_post_divider;1625	calc_pll_cs->max_pix_clock_pll_post_divider =1626			init_data->max_pix_clk_pll_post_divider;1627	calc_pll_cs->min_pll_ref_divider =1628			init_data->min_pll_ref_divider;1629	calc_pll_cs->max_pll_ref_divider =1630			init_data->max_pll_ref_divider;1631 1632	if (init_data->num_fract_fb_divider_decimal_point == 0 ||1633		init_data->num_fract_fb_divider_decimal_point_precision >1634				init_data->num_fract_fb_divider_decimal_point) {1635		DC_LOG_ERROR(1636			"The dec point num or precision is incorrect!");1637		return false;1638	}1639	if (init_data->num_fract_fb_divider_decimal_point_precision == 0) {1640		DC_LOG_ERROR(1641			"Incorrect fract feedback divider precision num!");1642		return false;1643	}1644 1645	calc_pll_cs->fract_fb_divider_decimal_points_num =1646				init_data->num_fract_fb_divider_decimal_point;1647	calc_pll_cs->fract_fb_divider_precision =1648			init_data->num_fract_fb_divider_decimal_point_precision;1649	calc_pll_cs->fract_fb_divider_factor = 1;1650	for (i = 0; i < calc_pll_cs->fract_fb_divider_decimal_points_num; ++i)1651		calc_pll_cs->fract_fb_divider_factor *= 10;1652 1653	calc_pll_cs->fract_fb_divider_precision_factor = 1;1654	for (1655		i = 0;1656		i < (calc_pll_cs->fract_fb_divider_decimal_points_num -1657				calc_pll_cs->fract_fb_divider_precision);1658		++i)1659		calc_pll_cs->fract_fb_divider_precision_factor *= 10;1660 1661	return true;1662}1663 1664bool dce110_clk_src_construct(1665	struct dce110_clk_src *clk_src,1666	struct dc_context *ctx,1667	struct dc_bios *bios,1668	enum clock_source_id id,1669	const struct dce110_clk_src_regs *regs,1670	const struct dce110_clk_src_shift *cs_shift,1671	const struct dce110_clk_src_mask *cs_mask)1672{1673	struct calc_pll_clock_source_init_data calc_pll_cs_init_data_hdmi;1674	struct calc_pll_clock_source_init_data calc_pll_cs_init_data;1675 1676	clk_src->base.ctx = ctx;1677	clk_src->bios = bios;1678	clk_src->base.id = id;1679	clk_src->base.funcs = &dce110_clk_src_funcs;1680 1681	clk_src->regs = regs;1682	clk_src->cs_shift = cs_shift;1683	clk_src->cs_mask = cs_mask;1684 1685	if (!clk_src->bios->fw_info_valid) {1686		ASSERT_CRITICAL(false);1687		goto unexpected_failure;1688	}1689 1690	clk_src->ext_clk_khz = clk_src->bios->fw_info.external_clock_source_frequency_for_dp;1691 1692	/* structure normally used with PLL ranges from ATOMBIOS; DS on by default */1693	calc_pll_cs_init_data.bp = bios;1694	calc_pll_cs_init_data.min_pix_clk_pll_post_divider = 1;1695	calc_pll_cs_init_data.max_pix_clk_pll_post_divider =1696			clk_src->cs_mask->PLL_POST_DIV_PIXCLK;1697	calc_pll_cs_init_data.min_pll_ref_divider =	1;1698	calc_pll_cs_init_data.max_pll_ref_divider =	clk_src->cs_mask->PLL_REF_DIV;1699	/* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/1700	calc_pll_cs_init_data.min_override_input_pxl_clk_pll_freq_khz =	0;1701	/* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/1702	calc_pll_cs_init_data.max_override_input_pxl_clk_pll_freq_khz =	0;1703	/*numberOfFractFBDividerDecimalPoints*/1704	calc_pll_cs_init_data.num_fract_fb_divider_decimal_point =1705			FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;1706	/*number of decimal point to round off for fractional feedback divider value*/1707	calc_pll_cs_init_data.num_fract_fb_divider_decimal_point_precision =1708			FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;1709	calc_pll_cs_init_data.ctx =	ctx;1710 1711	/*structure for HDMI, no SS or SS% <= 0.06% for 27 MHz Ref clock */1712	calc_pll_cs_init_data_hdmi.bp = bios;1713	calc_pll_cs_init_data_hdmi.min_pix_clk_pll_post_divider = 1;1714	calc_pll_cs_init_data_hdmi.max_pix_clk_pll_post_divider =1715			clk_src->cs_mask->PLL_POST_DIV_PIXCLK;1716	calc_pll_cs_init_data_hdmi.min_pll_ref_divider = 1;1717	calc_pll_cs_init_data_hdmi.max_pll_ref_divider = clk_src->cs_mask->PLL_REF_DIV;1718	/* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/1719	calc_pll_cs_init_data_hdmi.min_override_input_pxl_clk_pll_freq_khz = 13500;1720	/* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/1721	calc_pll_cs_init_data_hdmi.max_override_input_pxl_clk_pll_freq_khz = 27000;1722	/*numberOfFractFBDividerDecimalPoints*/1723	calc_pll_cs_init_data_hdmi.num_fract_fb_divider_decimal_point =1724			FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;1725	/*number of decimal point to round off for fractional feedback divider value*/1726	calc_pll_cs_init_data_hdmi.num_fract_fb_divider_decimal_point_precision =1727			FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;1728	calc_pll_cs_init_data_hdmi.ctx = ctx;1729 1730	clk_src->ref_freq_khz = clk_src->bios->fw_info.pll_info.crystal_frequency;1731 1732	if (clk_src->base.id == CLOCK_SOURCE_ID_EXTERNAL)1733		return true;1734 1735	/* PLL only from here on */1736	ss_info_from_atombios_create(clk_src);1737 1738	if (!calc_pll_max_vco_construct(1739			&clk_src->calc_pll,1740			&calc_pll_cs_init_data)) {1741		ASSERT_CRITICAL(false);1742		goto unexpected_failure;1743	}1744 1745 1746	calc_pll_cs_init_data_hdmi.1747			min_override_input_pxl_clk_pll_freq_khz = clk_src->ref_freq_khz/2;1748	calc_pll_cs_init_data_hdmi.1749			max_override_input_pxl_clk_pll_freq_khz = clk_src->ref_freq_khz;1750 1751 1752	if (!calc_pll_max_vco_construct(1753			&clk_src->calc_pll_hdmi, &calc_pll_cs_init_data_hdmi)) {1754		ASSERT_CRITICAL(false);1755		goto unexpected_failure;1756	}1757 1758	return true;1759 1760unexpected_failure:1761	return false;1762}1763 1764bool dce112_clk_src_construct(1765	struct dce110_clk_src *clk_src,1766	struct dc_context *ctx,1767	struct dc_bios *bios,1768	enum clock_source_id id,1769	const struct dce110_clk_src_regs *regs,1770	const struct dce110_clk_src_shift *cs_shift,1771	const struct dce110_clk_src_mask *cs_mask)1772{1773	clk_src->base.ctx = ctx;1774	clk_src->bios = bios;1775	clk_src->base.id = id;1776	clk_src->base.funcs = &dce112_clk_src_funcs;1777 1778	clk_src->regs = regs;1779	clk_src->cs_shift = cs_shift;1780	clk_src->cs_mask = cs_mask;1781 1782	if (!clk_src->bios->fw_info_valid) {1783		ASSERT_CRITICAL(false);1784		return false;1785	}1786 1787	clk_src->ext_clk_khz = clk_src->bios->fw_info.external_clock_source_frequency_for_dp;1788 1789	return true;1790}1791 1792bool dcn20_clk_src_construct(1793	struct dce110_clk_src *clk_src,1794	struct dc_context *ctx,1795	struct dc_bios *bios,1796	enum clock_source_id id,1797	const struct dce110_clk_src_regs *regs,1798	const struct dce110_clk_src_shift *cs_shift,1799	const struct dce110_clk_src_mask *cs_mask)1800{1801	bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask);1802 1803	clk_src->base.funcs = &dcn20_clk_src_funcs;1804 1805	return ret;1806}1807 1808bool dcn3_clk_src_construct(1809	struct dce110_clk_src *clk_src,1810	struct dc_context *ctx,1811	struct dc_bios *bios,1812	enum clock_source_id id,1813	const struct dce110_clk_src_regs *regs,1814	const struct dce110_clk_src_shift *cs_shift,1815	const struct dce110_clk_src_mask *cs_mask)1816{1817	bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask);1818 1819	clk_src->base.funcs = &dcn3_clk_src_funcs;1820 1821	return ret;1822}1823 1824bool dcn31_clk_src_construct(1825	struct dce110_clk_src *clk_src,1826	struct dc_context *ctx,1827	struct dc_bios *bios,1828	enum clock_source_id id,1829	const struct dce110_clk_src_regs *regs,1830	const struct dce110_clk_src_shift *cs_shift,1831	const struct dce110_clk_src_mask *cs_mask)1832{1833	bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask);1834 1835	clk_src->base.funcs = &dcn31_clk_src_funcs;1836 1837	return ret;1838}1839 1840bool dcn401_clk_src_construct(1841	struct dce110_clk_src *clk_src,1842	struct dc_context *ctx,1843	struct dc_bios *bios,1844	enum clock_source_id id,1845	const struct dce110_clk_src_regs *regs,1846	const struct dce110_clk_src_shift *cs_shift,1847	const struct dce110_clk_src_mask *cs_mask)1848{1849	bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask);1850 1851	clk_src->base.funcs = &dcn401_clk_src_funcs;1852 1853	return ret;1854}1855bool dcn301_clk_src_construct(1856	struct dce110_clk_src *clk_src,1857	struct dc_context *ctx,1858	struct dc_bios *bios,1859	enum clock_source_id id,1860	const struct dce110_clk_src_regs *regs,1861	const struct dce110_clk_src_shift *cs_shift,1862	const struct dce110_clk_src_mask *cs_mask)1863{1864	bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask);1865 1866	clk_src->base.funcs = &dcn3_clk_src_funcs;1867 1868	return ret;1869}1870