From d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 02:45:28 +0000
Subject: [PATCH] add boot partition  size

---
 kernel/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c |  873 +++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 533 insertions(+), 340 deletions(-)

diff --git a/kernel/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/kernel/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index ca13775..89cc852 100644
--- a/kernel/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/kernel/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -23,6 +23,8 @@
  *
  */
 
+#include <linux/slab.h>
+
 #include "dm_services.h"
 
 
@@ -33,6 +35,7 @@
 #include "include/logger_interface.h"
 
 #include "dce_clock_source.h"
+#include "clk_mgr.h"
 
 #include "reg_helper.h"
 
@@ -51,6 +54,8 @@
 #define FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM 6
 #define CALC_PLL_CLK_SRC_ERR_TOLERANCE 1
 #define MAX_PLL_CALC_ERROR 0xFFFFFFFF
+
+#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
 
 static const struct spread_spectrum_data *get_ss_data_entry(
 		struct dce110_clk_src *clk_src,
@@ -73,6 +78,11 @@
 	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_LVDS:
+		ss_parm = clk_src->lvds_ss_params;
+		entrys_num = clk_src->lvds_ss_params_cnt;
 		break;
 
 	case SIGNAL_TYPE_DISPLAY_PORT:
@@ -103,28 +113,28 @@
 }
 
 /**
-* 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)
-*/
+ * Function: calculate_fb_and_fractional_fb_divider
+ *
+ * * DESCRIPTION: Calculates feedback and fractional feedback dividers values
+ *
+ *PARAMETERS:
+ * targetPixelClock             Desired frequency in 100 Hz
+ * 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 target_pix_clk_100hz,
 		uint32_t ref_divider,
 		uint32_t post_divider,
 		uint32_t *feedback_divider_param,
@@ -133,11 +143,11 @@
 	uint64_t feedback_divider;
 
 	feedback_divider =
-		(uint64_t)target_pix_clk_khz * ref_divider * post_divider;
+		(uint64_t)target_pix_clk_100hz * 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);
+	feedback_divider = div_u64(feedback_divider, calc_pll_cs->ref_freq_khz * 10ull);
 
 /*Round to the number of precision
  * The following code replace the old code (ullfeedbackDivider + 5)/10
@@ -178,8 +188,8 @@
 *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
+* It returns	- true if error is within tolerance
+*		- false if error is not within tolerance
 */
 static bool calc_fb_divider_checking_tolerance(
 		struct calc_pll_clock_source *calc_pll_cs,
@@ -190,36 +200,36 @@
 {
 	uint32_t feedback_divider;
 	uint32_t fract_feedback_divider;
-	uint32_t actual_calculated_clock_khz;
+	uint32_t actual_calculated_clock_100hz;
 	uint32_t abs_err;
-	uint64_t actual_calc_clk_khz;
+	uint64_t actual_calc_clk_100hz;
 
 	calculate_fb_and_fractional_fb_divider(
 			calc_pll_cs,
-			pll_settings->adjusted_pix_clk,
+			pll_settings->adjusted_pix_clk_100hz,
 			ref_divider,
 			post_divider,
 			&feedback_divider,
 			&fract_feedback_divider);
 
 	/*Actual calculated value*/
-	actual_calc_clk_khz = (uint64_t)feedback_divider *
+	actual_calc_clk_100hz = (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,
+	actual_calc_clk_100hz *= calc_pll_cs->ref_freq_khz * 10;
+	actual_calc_clk_100hz =
+		div_u64(actual_calc_clk_100hz,
 			ref_divider * post_divider *
 				calc_pll_cs->fract_fb_divider_factor);
 
-	actual_calculated_clock_khz = (uint32_t)(actual_calc_clk_khz);
+	actual_calculated_clock_100hz = (uint32_t)(actual_calc_clk_100hz);
 
-	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;
+	abs_err = (actual_calculated_clock_100hz >
+					pll_settings->adjusted_pix_clk_100hz)
+			? actual_calculated_clock_100hz -
+					pll_settings->adjusted_pix_clk_100hz
+			: pll_settings->adjusted_pix_clk_100hz -
+						actual_calculated_clock_100hz;
 
 	if (abs_err <= tolerance) {
 		/*found good values*/
@@ -228,10 +238,10 @@
 		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->calculated_pix_clk_100hz =
+			actual_calculated_clock_100hz;
 		pll_settings->vco_freq =
-			actual_calculated_clock_khz * post_divider;
+			actual_calculated_clock_100hz * post_divider / 10;
 		return true;
 	}
 	return false;
@@ -252,8 +262,8 @@
 
 /* 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;
+	tolerance = (pll_settings->adjusted_pix_clk_100hz * err_tolerance) /
+									100000;
 	if (tolerance < CALC_PLL_CLK_SRC_ERR_TOLERANCE)
 		tolerance = CALC_PLL_CLK_SRC_ERR_TOLERANCE;
 
@@ -289,7 +299,7 @@
 	uint32_t min_ref_divider;
 	uint32_t max_ref_divider;
 
-	if (pll_settings->adjusted_pix_clk == 0) {
+	if (pll_settings->adjusted_pix_clk_100hz == 0) {
 		DC_LOG_ERROR(
 			"%s Bad requested pixel clock", __func__);
 		return MAX_PLL_CALC_ERROR;
@@ -301,21 +311,21 @@
 		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_100hz <
+						calc_pll_cs->min_vco_khz * 10) {
+			min_post_divider = calc_pll_cs->min_vco_khz * 10 /
+					pll_settings->adjusted_pix_clk_100hz;
 			if ((min_post_divider *
-					pll_settings->adjusted_pix_clk) <
-						calc_pll_cs->min_vco_khz)
+					pll_settings->adjusted_pix_clk_100hz) <
+						calc_pll_cs->min_vco_khz * 10)
 				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;
+		if (max_post_divider * pll_settings->adjusted_pix_clk_100hz
+				> calc_pll_cs->max_vco_khz * 10)
+			max_post_divider = calc_pll_cs->max_vco_khz * 10 /
+					pll_settings->adjusted_pix_clk_100hz;
 	}
 
 /* 2) Find Reference divider ranges
@@ -387,47 +397,47 @@
 		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;
+	uint32_t actual_pix_clk_100hz = 0;
+	uint32_t requested_clk_100hz = 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;
+		requested_clk_100hz = pix_clk_params->requested_pix_clk_100hz;
 		if (pix_clk_params->pixel_encoding != PIXEL_ENCODING_YCBCR422) {
 			switch (pix_clk_params->color_depth) {
 			case COLOR_DEPTH_101010:
-				requested_clk_khz = (requested_clk_khz * 5) >> 2;
+				requested_clk_100hz = (requested_clk_100hz * 5) >> 2;
 				break; /* x1.25*/
 			case COLOR_DEPTH_121212:
-				requested_clk_khz = (requested_clk_khz * 6) >> 2;
+				requested_clk_100hz = (requested_clk_100hz * 6) >> 2;
 				break; /* x1.5*/
 			case COLOR_DEPTH_161616:
-				requested_clk_khz = requested_clk_khz * 2;
+				requested_clk_100hz = requested_clk_100hz * 2;
 				break; /* x2.0*/
 			default:
 				break;
 			}
 		}
-		actual_pix_clk_khz = requested_clk_khz;
+		actual_pix_clk_100hz = requested_clk_100hz;
 	}
 		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;
+		requested_clk_100hz = pix_clk_params->requested_sym_clk * 10;
+		actual_pix_clk_100hz = pix_clk_params->requested_pix_clk_100hz;
 		break;
 
 	default:
-		requested_clk_khz = pix_clk_params->requested_pix_clk;
-		actual_pix_clk_khz = pix_clk_params->requested_pix_clk;
+		requested_clk_100hz = pix_clk_params->requested_pix_clk_100hz;
+		actual_pix_clk_100hz = pix_clk_params->requested_pix_clk_100hz;
 		break;
 	}
 
-	bp_adjust_pixel_clock_params.pixel_clock = requested_clk_khz;
+	bp_adjust_pixel_clock_params.pixel_clock = requested_clk_100hz / 10;
 	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;
@@ -436,9 +446,9 @@
 	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->actual_pix_clk_100hz = actual_pix_clk_100hz;
+		pll_settings->adjusted_pix_clk_100hz =
+			bp_adjust_pixel_clock_params.adjusted_pixel_clock * 10;
 		pll_settings->reference_divider =
 			bp_adjust_pixel_clock_params.reference_divider;
 		pll_settings->pix_clk_post_divider =
@@ -485,7 +495,7 @@
 		const struct spread_spectrum_data *ss_data = get_ss_data_entry(
 					clk_src,
 					pix_clk_params->signal_type,
-					pll_settings->adjusted_pix_clk);
+					pll_settings->adjusted_pix_clk_100hz / 10);
 
 		if (NULL != ss_data)
 			pll_settings->ss_percentage = ss_data->percentage;
@@ -497,13 +507,13 @@
 		 * to continue. */
 		DC_LOG_ERROR(
 			"%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;
+		pll_settings->actual_pix_clk_100hz =
+				pix_clk_params->requested_pix_clk_100hz;
+		pll_settings->adjusted_pix_clk_100hz =
+				pix_clk_params->requested_pix_clk_100hz;
 
 		if (dc_is_dp_signal(pix_clk_params->signal_type))
-			pll_settings->adjusted_pix_clk = 100000;
+			pll_settings->adjusted_pix_clk_100hz = 1000000;
 	}
 
 	/* Calculate Dividers */
@@ -528,28 +538,30 @@
 		struct pll_settings *pll_settings,
 		struct pixel_clk_params *pix_clk_params)
 {
-	uint32_t actualPixelClockInKHz;
+	uint32_t actual_pixel_clock_100hz;
 
-	actualPixelClockInKHz = pix_clk_params->requested_pix_clk;
+	actual_pixel_clock_100hz = pix_clk_params->requested_pix_clk_100hz;
 	/* Calculate Dividers */
 	if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) {
 		switch (pix_clk_params->color_depth) {
 		case COLOR_DEPTH_101010:
-			actualPixelClockInKHz = (actualPixelClockInKHz * 5) >> 2;
+			actual_pixel_clock_100hz = (actual_pixel_clock_100hz * 5) >> 2;
+			actual_pixel_clock_100hz -= actual_pixel_clock_100hz % 10;
 			break;
 		case COLOR_DEPTH_121212:
-			actualPixelClockInKHz = (actualPixelClockInKHz * 6) >> 2;
+			actual_pixel_clock_100hz = (actual_pixel_clock_100hz * 6) >> 2;
+			actual_pixel_clock_100hz -= actual_pixel_clock_100hz % 10;
 			break;
 		case COLOR_DEPTH_161616:
-			actualPixelClockInKHz = actualPixelClockInKHz * 2;
+			actual_pixel_clock_100hz = actual_pixel_clock_100hz * 2;
 			break;
 		default:
 			break;
 		}
 	}
-	pll_settings->actual_pix_clk = actualPixelClockInKHz;
-	pll_settings->adjusted_pix_clk = actualPixelClockInKHz;
-	pll_settings->calculated_pix_clk = pix_clk_params->requested_pix_clk;
+	pll_settings->actual_pix_clk_100hz = actual_pixel_clock_100hz;
+	pll_settings->adjusted_pix_clk_100hz = actual_pixel_clock_100hz;
+	pll_settings->calculated_pix_clk_100hz = pix_clk_params->requested_pix_clk_100hz;
 }
 
 static uint32_t dce110_get_pix_clk_dividers(
@@ -562,7 +574,7 @@
 	DC_LOGGER_INIT();
 
 	if (pix_clk_params == NULL || pll_settings == NULL
-			|| pix_clk_params->requested_pix_clk == 0) {
+			|| pix_clk_params->requested_pix_clk_100hz == 0) {
 		DC_LOG_ERROR(
 			"%s: Invalid parameters!!\n", __func__);
 		return pll_calc_error;
@@ -572,122 +584,49 @@
 
 	if (cs->id == CLOCK_SOURCE_ID_DP_DTO ||
 			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;
+		pll_settings->adjusted_pix_clk_100hz = clk_src->ext_clk_khz * 10;
+		pll_settings->calculated_pix_clk_100hz = clk_src->ext_clk_khz * 10;
+		pll_settings->actual_pix_clk_100hz =
+					pix_clk_params->requested_pix_clk_100hz;
 		return 0;
 	}
 
-	switch (cs->ctx->dce_version) {
-	case DCE_VERSION_8_0:
-	case DCE_VERSION_8_1:
-	case DCE_VERSION_8_3:
-	case DCE_VERSION_10_0:
-	case DCE_VERSION_11_0:
-		pll_calc_error =
-			dce110_get_pix_clk_dividers_helper(clk_src,
+	pll_calc_error = dce110_get_pix_clk_dividers_helper(clk_src,
 			pll_settings, pix_clk_params);
-		break;
-	case DCE_VERSION_11_2:
-	case DCE_VERSION_11_22:
-	case DCE_VERSION_12_0:
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
-	case DCN_VERSION_1_0:
-#endif
-
-		dce112_get_pix_clk_dividers_helper(clk_src,
-				pll_settings, pix_clk_params);
-		break;
-	default:
-		break;
-	}
 
 	return pll_calc_error;
 }
 
-static uint32_t dce110_get_pll_pixel_rate_in_hz(
-	struct clock_source *cs,
-	struct pixel_clk_params *pix_clk_params,
-	struct pll_settings *pll_settings)
+static uint32_t dce112_get_pix_clk_dividers(
+		struct clock_source *cs,
+		struct pixel_clk_params *pix_clk_params,
+		struct pll_settings *pll_settings)
 {
-	uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
-	struct dc *dc_core = cs->ctx->dc;
-	struct dc_state *context = dc_core->current_state;
-	struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst];
-
-	/* This function need separate to different DCE version, before separate, just use pixel clock */
-	return pipe_ctx->stream->phy_pix_clk;
-
-}
-
-static uint32_t dce110_get_dp_pixel_rate_from_combo_phy_pll(
-	struct clock_source *cs,
-	struct pixel_clk_params *pix_clk_params,
-	struct pll_settings *pll_settings)
-{
-	uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
-	struct dc *dc_core = cs->ctx->dc;
-	struct dc_state *context = dc_core->current_state;
-	struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[inst];
-
-	/* This function need separate to different DCE version, before separate, just use pixel clock */
-	return pipe_ctx->stream->phy_pix_clk;
-}
-
-static uint32_t dce110_get_d_to_pixel_rate_in_hz(
-	struct clock_source *cs,
-	struct pixel_clk_params *pix_clk_params,
-	struct pll_settings *pll_settings)
-{
-	uint32_t inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
 	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(cs);
-	int dto_enabled = 0;
-	struct fixed31_32 pix_rate;
+	DC_LOGGER_INIT();
 
-	REG_GET(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, &dto_enabled);
-
-	if (dto_enabled) {
-		uint32_t phase = 0;
-		uint32_t modulo = 0;
-		REG_GET(PHASE[inst], DP_DTO0_PHASE, &phase);
-		REG_GET(MODULO[inst], DP_DTO0_MODULO, &modulo);
-
-		if (modulo == 0) {
-			return 0;
-		}
-
-		pix_rate = dc_fixpt_from_int(clk_src->ref_freq_khz);
-		pix_rate = dc_fixpt_mul_int(pix_rate, 1000);
-		pix_rate = dc_fixpt_mul_int(pix_rate, phase);
-		pix_rate = dc_fixpt_div_int(pix_rate, modulo);
-
-		return dc_fixpt_round(pix_rate);
-	} else {
-		return dce110_get_dp_pixel_rate_from_combo_phy_pll(cs, pix_clk_params, pll_settings);
-	}
-}
-
-static uint32_t dce110_get_pix_rate_in_hz(
-	struct clock_source *cs,
-	struct pixel_clk_params *pix_clk_params,
-	struct pll_settings *pll_settings)
-{
-	uint32_t pix_rate = 0;
-	switch (pix_clk_params->signal_type) {
-	case	SIGNAL_TYPE_DISPLAY_PORT:
-	case	SIGNAL_TYPE_DISPLAY_PORT_MST:
-	case	SIGNAL_TYPE_EDP:
-	case	SIGNAL_TYPE_VIRTUAL:
-		pix_rate = dce110_get_d_to_pixel_rate_in_hz(cs, pix_clk_params, pll_settings);
-		break;
-	case	SIGNAL_TYPE_HDMI_TYPE_A:
-	default:
-		pix_rate = dce110_get_pll_pixel_rate_in_hz(cs, pix_clk_params, pll_settings);
-		break;
+	if (pix_clk_params == NULL || pll_settings == NULL
+			|| pix_clk_params->requested_pix_clk_100hz == 0) {
+		DC_LOG_ERROR(
+			"%s: Invalid parameters!!\n", __func__);
+		return -1;
 	}
 
-	return pix_rate;
+	memset(pll_settings, 0, sizeof(*pll_settings));
+
+	if (cs->id == CLOCK_SOURCE_ID_DP_DTO ||
+			cs->id == CLOCK_SOURCE_ID_EXTERNAL) {
+		pll_settings->adjusted_pix_clk_100hz = clk_src->ext_clk_khz * 10;
+		pll_settings->calculated_pix_clk_100hz = clk_src->ext_clk_khz * 10;
+		pll_settings->actual_pix_clk_100hz =
+					pix_clk_params->requested_pix_clk_100hz;
+		return -1;
+	}
+
+	dce112_get_pix_clk_dividers_helper(clk_src,
+			pll_settings, pix_clk_params);
+
+	return 0;
 }
 
 static bool disable_spread_spectrum(struct dce110_clk_src *clk_src)
@@ -782,7 +721,7 @@
 	ss_data = get_ss_data_entry(
 			clk_src,
 			signal,
-			pll_settings->calculated_pix_clk);
+			pll_settings->calculated_pix_clk_100hz / 10);
 
 /* Pixel clock PLL has been programmed to generate desired pixel clock,
  * now enable SS on pixel clock */
@@ -909,15 +848,88 @@
 	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
 	struct bp_pixel_clock_parameters bp_pc_params = {0};
 
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+	/* First disable SS
+	 * ATOMBIOS will enable by default SS on PLL for DP,
+	 * do not disable it here
+	 */
+	if (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL &&
+			!dc_is_dp_signal(pix_clk_params->signal_type) &&
+			clock_source->ctx->dce_version <= DCE_VERSION_11_0)
+		disable_spread_spectrum(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 = clock_source->id;
+	bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz;
+	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.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.flags.SET_EXTERNAL_REF_DIV_SRC =
+					pll_settings->use_external_clk;
+
+	switch (pix_clk_params->color_depth) {
+	case COLOR_DEPTH_101010:
+		bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_30;
+		break;
+	case COLOR_DEPTH_121212:
+		bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_36;
+		break;
+	case COLOR_DEPTH_161616:
+		bp_pc_params.color_depth = TRANSMITTER_COLOR_DEPTH_48;
+		break;
+	default:
+		break;
+	}
+
+	if (clk_src->bios->funcs->set_pixel_clock(
+			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 (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL
+			&& !dc_is_dp_signal(pix_clk_params->signal_type)) {
+
+		if (pix_clk_params->flags.ENABLE_SS)
+			if (!enable_spread_spectrum(clk_src,
+							pix_clk_params->signal_type,
+							pll_settings))
+				return false;
+
+		/* Resync deep color DTO */
+		dce110_program_pixel_clk_resync(clk_src,
+					pix_clk_params->signal_type,
+					pix_clk_params->color_depth);
+	}
+
+	return true;
+}
+
+static bool dce112_program_pix_clk(
+		struct clock_source *clock_source,
+		struct pixel_clk_params *pix_clk_params,
+		struct pll_settings *pll_settings)
+{
+	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
+	struct bp_pixel_clock_parameters bp_pc_params = {0};
+
+#if defined(CONFIG_DRM_AMD_DC_DCN)
 	if (IS_FPGA_MAXIMUS_DC(clock_source->ctx->dce_environment)) {
 		unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
-		unsigned dp_dto_ref_kHz = 700000;
-		unsigned clock_kHz = pll_settings->actual_pix_clk;
+		unsigned dp_dto_ref_100hz = 7000000;
+		unsigned clock_100hz = pll_settings->actual_pix_clk_100hz;
 
 		/* Set DTO values: phase = target clock, modulo = reference clock */
-		REG_WRITE(PHASE[inst], clock_kHz);
-		REG_WRITE(MODULO[inst], dp_dto_ref_kHz);
+		REG_WRITE(PHASE[inst], clock_100hz);
+		REG_WRITE(MODULO[inst], dp_dto_ref_100hz);
 
 		/* Enable DTO */
 		REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1);
@@ -936,81 +948,32 @@
 	/*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/
 	bp_pc_params.controller_id = pix_clk_params->controller_id;
 	bp_pc_params.pll_id = clock_source->id;
-	bp_pc_params.target_pixel_clock = pll_settings->actual_pix_clk;
+	bp_pc_params.target_pixel_clock_100hz = pll_settings->actual_pix_clk_100hz;
 	bp_pc_params.encoder_object_id = pix_clk_params->encoder_object_id;
 	bp_pc_params.signal_type = pix_clk_params->signal_type;
 
-	switch (clock_source->ctx->dce_version) {
-	case DCE_VERSION_8_0:
-	case DCE_VERSION_8_1:
-	case DCE_VERSION_8_3:
-	case DCE_VERSION_10_0:
-	case DCE_VERSION_11_0:
-		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.flags.SET_EXTERNAL_REF_DIV_SRC =
+	if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
+		bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC =
 						pll_settings->use_external_clk;
-
-		if (clk_src->bios->funcs->set_pixel_clock(
-				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 (clock_source->id != CLOCK_SOURCE_ID_EXTERNAL
-				&& !dc_is_dp_signal(pix_clk_params->signal_type)) {
-
-			if (pix_clk_params->flags.ENABLE_SS)
-				if (!enable_spread_spectrum(clk_src,
-								pix_clk_params->signal_type,
-								pll_settings))
-					return false;
-
-			/* Resync deep color DTO */
-			dce110_program_pixel_clk_resync(clk_src,
-						pix_clk_params->signal_type,
-						pix_clk_params->color_depth);
+		bp_pc_params.flags.SET_XTALIN_REF_SRC =
+						!pll_settings->use_external_clk;
+		if (pix_clk_params->flags.SUPPORT_YCBCR420) {
+			bp_pc_params.flags.SUPPORT_YUV_420 = 1;
 		}
-
-		break;
-	case DCE_VERSION_11_2:
-	case DCE_VERSION_11_22:
-	case DCE_VERSION_12_0:
-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
-	case DCN_VERSION_1_0:
-#endif
-
-		if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO) {
-			bp_pc_params.flags.SET_GENLOCK_REF_DIV_SRC =
-							pll_settings->use_external_clk;
-			bp_pc_params.flags.SET_XTALIN_REF_SRC =
-							!pll_settings->use_external_clk;
-			if (pix_clk_params->flags.SUPPORT_YCBCR420) {
-				bp_pc_params.flags.SUPPORT_YUV_420 = 1;
-			}
-		}
-		if (clk_src->bios->funcs->set_pixel_clock(
-				clk_src->bios, &bp_pc_params) != BP_RESULT_OK)
-			return false;
-		/* Resync deep color DTO */
-		if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO)
-			dce112_program_pixel_clk_resync(clk_src,
-						pix_clk_params->signal_type,
-						pix_clk_params->color_depth,
-						pix_clk_params->flags.SUPPORT_YCBCR420);
-		break;
-	default:
-		break;
 	}
+	if (clk_src->bios->funcs->set_pixel_clock(
+			clk_src->bios, &bp_pc_params) != BP_RESULT_OK)
+		return false;
+	/* Resync deep color DTO */
+	if (clock_source->id != CLOCK_SOURCE_ID_DP_DTO)
+		dce112_program_pixel_clk_resync(clk_src,
+					pix_clk_params->signal_type,
+					pix_clk_params->color_depth,
+					pix_clk_params->flags.SUPPORT_YCBCR420);
 
 	return true;
 }
+
 
 static bool dce110_clock_source_power_down(
 		struct clock_source *clk_src)
@@ -1035,15 +998,194 @@
 	return bp_result == BP_RESULT_OK;
 }
 
+static bool get_pixel_clk_frequency_100hz(
+		const struct clock_source *clock_source,
+		unsigned int inst,
+		unsigned int *pixel_clk_khz)
+{
+	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
+	unsigned int clock_hz = 0;
+
+	if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) {
+		clock_hz = REG_READ(PHASE[inst]);
+
+		/* NOTE: There is agreement with VBIOS here that MODULO is
+		 * programmed equal to DPREFCLK, in which case PHASE will be
+		 * equivalent to pixel clock.
+		 */
+		*pixel_clk_khz = clock_hz / 100;
+		return true;
+	}
+
+	return false;
+}
+
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
+/* this table is use to find *1.001 and /1.001 pixel rates from non-precise pixel rate */
+const struct pixel_rate_range_table_entry video_optimized_pixel_rates[] = {
+	// /1.001 rates
+	{25170, 25180, 25200, 1000, 1001},	//25.2MHz   ->   25.17
+	{59340, 59350, 59400, 1000, 1001},	//59.4Mhz   ->   59.340
+	{74170, 74180, 74250, 1000, 1001},	//74.25Mhz  ->   74.1758
+	{125870, 125880, 126000, 1000, 1001},	//126Mhz    ->  125.87
+	{148350, 148360, 148500, 1000, 1001},	//148.5Mhz  ->  148.3516
+	{167830, 167840, 168000, 1000, 1001},	//168Mhz    ->  167.83
+	{222520, 222530, 222750, 1000, 1001},	//222.75Mhz ->  222.527
+	{257140, 257150, 257400, 1000, 1001},	//257.4Mhz  ->  257.1429
+	{296700, 296710, 297000, 1000, 1001},	//297Mhz    ->  296.7033
+	{342850, 342860, 343200, 1000, 1001},	//343.2Mhz  ->  342.857
+	{395600, 395610, 396000, 1000, 1001},	//396Mhz    ->  395.6
+	{409090, 409100, 409500, 1000, 1001},	//409.5Mhz  ->  409.091
+	{445050, 445060, 445500, 1000, 1001},	//445.5Mhz  ->  445.055
+	{467530, 467540, 468000, 1000, 1001},	//468Mhz    ->  467.5325
+	{519230, 519240, 519750, 1000, 1001},	//519.75Mhz ->  519.231
+	{525970, 525980, 526500, 1000, 1001},	//526.5Mhz  ->  525.974
+	{545450, 545460, 546000, 1000, 1001},	//546Mhz    ->  545.455
+	{593400, 593410, 594000, 1000, 1001},	//594Mhz    ->  593.4066
+	{623370, 623380, 624000, 1000, 1001},	//624Mhz    ->  623.377
+	{692300, 692310, 693000, 1000, 1001},	//693Mhz    ->  692.308
+	{701290, 701300, 702000, 1000, 1001},	//702Mhz    ->  701.2987
+	{791200, 791210, 792000, 1000, 1001},	//792Mhz    ->  791.209
+	{890100, 890110, 891000, 1000, 1001},	//891Mhz    ->  890.1099
+	{1186810, 1186820, 1188000, 1000, 1001},//1188Mhz   -> 1186.8131
+
+	// *1.001 rates
+	{27020, 27030, 27000, 1001, 1000}, //27Mhz
+	{54050, 54060, 54000, 1001, 1000}, //54Mhz
+	{108100, 108110, 108000, 1001, 1000},//108Mhz
+};
+
+const struct pixel_rate_range_table_entry *look_up_in_video_optimized_rate_tlb(
+		unsigned int pixel_rate_khz)
+{
+	int i;
+
+	for (i = 0; i < NUM_ELEMENTS(video_optimized_pixel_rates); i++) {
+		const struct pixel_rate_range_table_entry *e = &video_optimized_pixel_rates[i];
+
+		if (e->range_min_khz <= pixel_rate_khz && pixel_rate_khz <= e->range_max_khz) {
+			return e;
+		}
+	}
+
+	return NULL;
+}
+#endif
+
+static bool dcn20_program_pix_clk(
+		struct clock_source *clock_source,
+		struct pixel_clk_params *pix_clk_params,
+		struct pll_settings *pll_settings)
+{
+	dce112_program_pix_clk(clock_source, pix_clk_params, pll_settings);
+
+	return true;
+}
+
+static const struct clock_source_funcs dcn20_clk_src_funcs = {
+	.cs_power_down = dce110_clock_source_power_down,
+	.program_pix_clk = dcn20_program_pix_clk,
+	.get_pix_clk_dividers = dce112_get_pix_clk_dividers,
+	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
+};
+
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
+static bool dcn3_program_pix_clk(
+		struct clock_source *clock_source,
+		struct pixel_clk_params *pix_clk_params,
+		struct pll_settings *pll_settings)
+{
+	struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
+	unsigned int inst = pix_clk_params->controller_id - CONTROLLER_ID_D0;
+	unsigned int dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dprefclk_khz;
+	const struct pixel_rate_range_table_entry *e =
+			look_up_in_video_optimized_rate_tlb(pix_clk_params->requested_pix_clk_100hz / 10);
+
+	// For these signal types Driver to program DP_DTO without calling VBIOS Command table
+	if (dc_is_dp_signal(pix_clk_params->signal_type)) {
+		if (e) {
+			/* Set DTO values: phase = target clock, modulo = reference clock*/
+			REG_WRITE(PHASE[inst], e->target_pixel_rate_khz * e->mult_factor);
+			REG_WRITE(MODULO[inst], dp_dto_ref_khz * e->div_factor);
+		} else {
+			/* Set DTO values: phase = target clock, modulo = reference clock*/
+			REG_WRITE(PHASE[inst], pll_settings->actual_pix_clk_100hz * 100);
+			REG_WRITE(MODULO[inst], dp_dto_ref_khz * 1000);
+		}
+		REG_UPDATE(PIXEL_RATE_CNTL[inst], DP_DTO0_ENABLE, 1);
+	} else
+		// For other signal types(HDMI_TYPE_A, DVI) Driver still to call VBIOS Command table
+		dce112_program_pix_clk(clock_source, pix_clk_params, pll_settings);
+
+	return true;
+}
+
+static uint32_t dcn3_get_pix_clk_dividers(
+		struct clock_source *cs,
+		struct pixel_clk_params *pix_clk_params,
+		struct pll_settings *pll_settings)
+{
+	unsigned long long actual_pix_clk_100Hz = pix_clk_params->requested_pix_clk_100hz;
+	struct dce110_clk_src *clk_src;
+
+	clk_src = TO_DCE110_CLK_SRC(cs);
+	DC_LOGGER_INIT();
+
+	if (pix_clk_params == NULL || pll_settings == NULL
+			|| pix_clk_params->requested_pix_clk_100hz == 0) {
+		DC_LOG_ERROR(
+			"%s: Invalid parameters!!\n", __func__);
+		return -1;
+	}
+
+	memset(pll_settings, 0, sizeof(*pll_settings));
+	/* Adjust for HDMI Type A deep color */
+	if (pix_clk_params->signal_type == SIGNAL_TYPE_HDMI_TYPE_A) {
+		switch (pix_clk_params->color_depth) {
+		case COLOR_DEPTH_101010:
+			actual_pix_clk_100Hz = (actual_pix_clk_100Hz * 5) >> 2;
+			break;
+		case COLOR_DEPTH_121212:
+			actual_pix_clk_100Hz = (actual_pix_clk_100Hz * 6) >> 2;
+			break;
+		case COLOR_DEPTH_161616:
+			actual_pix_clk_100Hz = actual_pix_clk_100Hz * 2;
+			break;
+		default:
+			break;
+		}
+	}
+	pll_settings->actual_pix_clk_100hz = (unsigned int) actual_pix_clk_100Hz;
+	pll_settings->adjusted_pix_clk_100hz = (unsigned int) actual_pix_clk_100Hz;
+	pll_settings->calculated_pix_clk_100hz = (unsigned int) actual_pix_clk_100Hz;
+
+	return 0;
+}
+
+static const struct clock_source_funcs dcn3_clk_src_funcs = {
+	.cs_power_down = dce110_clock_source_power_down,
+	.program_pix_clk = dcn3_program_pix_clk,
+	.get_pix_clk_dividers = dcn3_get_pix_clk_dividers,
+	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
+};
+#endif
 /*****************************************/
 /* Constructor                           */
 /*****************************************/
+
+static const struct clock_source_funcs dce112_clk_src_funcs = {
+	.cs_power_down = dce110_clock_source_power_down,
+	.program_pix_clk = dce112_program_pix_clk,
+	.get_pix_clk_dividers = dce112_get_pix_clk_dividers,
+	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
+};
 static const 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,
-	.get_pix_rate_in_hz = dce110_get_pix_rate_in_hz
+	.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
 };
+
 
 static void get_ss_info_from_atombios(
 		struct dce110_clk_src *clk_src,
@@ -1184,6 +1326,11 @@
 		AS_SIGNAL_TYPE_DVI,
 		&clk_src->dvi_ss_params,
 		&clk_src->dvi_ss_params_cnt);
+	get_ss_info_from_atombios(
+		clk_src,
+		AS_SIGNAL_TYPE_LVDS,
+		&clk_src->lvds_ss_params,
+		&clk_src->lvds_ss_params_cnt);
 }
 
 static bool calc_pll_max_vco_construct(
@@ -1191,37 +1338,36 @@
 			struct calc_pll_clock_source_init_data *init_data)
 {
 	uint32_t i;
-	struct dc_firmware_info fw_info = { { 0 } };
+	struct dc_firmware_info *fw_info;
 	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)
+	if (!init_data->bp->fw_info_valid)
 		return false;
 
+	fw_info = &init_data->bp->fw_info;
 	calc_pll_cs->ctx = init_data->ctx;
-	calc_pll_cs->ref_freq_khz = fw_info.pll_info.crystal_frequency;
+	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;
+			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;
+			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;
+			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;
+			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;
@@ -1273,7 +1419,6 @@
 	const struct dce110_clk_src_shift *cs_shift,
 	const struct dce110_clk_src_mask *cs_mask)
 {
-	struct dc_firmware_info fw_info = { { 0 } };
 	struct calc_pll_clock_source_init_data calc_pll_cs_init_data_hdmi;
 	struct calc_pll_clock_source_init_data calc_pll_cs_init_data;
 
@@ -1286,90 +1431,77 @@
 	clk_src->cs_shift = cs_shift;
 	clk_src->cs_mask = cs_mask;
 
-	if (clk_src->bios->funcs->get_firmware_info(
-			clk_src->bios, &fw_info) != BP_RESULT_OK) {
+	if (!clk_src->bios->fw_info_valid) {
 		ASSERT_CRITICAL(false);
 		goto unexpected_failure;
 	}
 
-	clk_src->ext_clk_khz =
-			fw_info.external_clock_source_frequency_for_dp;
+	clk_src->ext_clk_khz = clk_src->bios->fw_info.external_clock_source_frequency_for_dp;
 
-	switch (clk_src->base.ctx->dce_version) {
-	case DCE_VERSION_8_0:
-	case DCE_VERSION_8_1:
-	case DCE_VERSION_8_3:
-	case DCE_VERSION_10_0:
-	case DCE_VERSION_11_0:
+	/* structure normally used with PLL ranges from ATOMBIOS; DS on by default */
+	calc_pll_cs_init_data.bp = bios;
+	calc_pll_cs_init_data.min_pix_clk_pll_post_divider = 1;
+	calc_pll_cs_init_data.max_pix_clk_pll_post_divider =
+			clk_src->cs_mask->PLL_POST_DIV_PIXCLK;
+	calc_pll_cs_init_data.min_pll_ref_divider =	1;
+	calc_pll_cs_init_data.max_pll_ref_divider =	clk_src->cs_mask->PLL_REF_DIV;
+	/* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
+	calc_pll_cs_init_data.min_override_input_pxl_clk_pll_freq_khz =	0;
+	/* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
+	calc_pll_cs_init_data.max_override_input_pxl_clk_pll_freq_khz =	0;
+	/*numberOfFractFBDividerDecimalPoints*/
+	calc_pll_cs_init_data.num_fract_fb_divider_decimal_point =
+			FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;
+	/*number of decimal point to round off for fractional feedback divider value*/
+	calc_pll_cs_init_data.num_fract_fb_divider_decimal_point_precision =
+			FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;
+	calc_pll_cs_init_data.ctx =	ctx;
 
-		/* structure normally used with PLL ranges from ATOMBIOS; DS on by default */
-		calc_pll_cs_init_data.bp = bios;
-		calc_pll_cs_init_data.min_pix_clk_pll_post_divider = 1;
-		calc_pll_cs_init_data.max_pix_clk_pll_post_divider =
-				clk_src->cs_mask->PLL_POST_DIV_PIXCLK;
-		calc_pll_cs_init_data.min_pll_ref_divider =	1;
-		calc_pll_cs_init_data.max_pll_ref_divider =	clk_src->cs_mask->PLL_REF_DIV;
-		/* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
-		calc_pll_cs_init_data.min_override_input_pxl_clk_pll_freq_khz =	0;
-		/* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
-		calc_pll_cs_init_data.max_override_input_pxl_clk_pll_freq_khz =	0;
-		/*numberOfFractFBDividerDecimalPoints*/
-		calc_pll_cs_init_data.num_fract_fb_divider_decimal_point =
-				FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;
-		/*number of decimal point to round off for fractional feedback divider value*/
-		calc_pll_cs_init_data.num_fract_fb_divider_decimal_point_precision =
-				FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;
-		calc_pll_cs_init_data.ctx =	ctx;
+	/*structure for HDMI, no SS or SS% <= 0.06% for 27 MHz Ref clock */
+	calc_pll_cs_init_data_hdmi.bp = bios;
+	calc_pll_cs_init_data_hdmi.min_pix_clk_pll_post_divider = 1;
+	calc_pll_cs_init_data_hdmi.max_pix_clk_pll_post_divider =
+			clk_src->cs_mask->PLL_POST_DIV_PIXCLK;
+	calc_pll_cs_init_data_hdmi.min_pll_ref_divider = 1;
+	calc_pll_cs_init_data_hdmi.max_pll_ref_divider = clk_src->cs_mask->PLL_REF_DIV;
+	/* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
+	calc_pll_cs_init_data_hdmi.min_override_input_pxl_clk_pll_freq_khz = 13500;
+	/* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
+	calc_pll_cs_init_data_hdmi.max_override_input_pxl_clk_pll_freq_khz = 27000;
+	/*numberOfFractFBDividerDecimalPoints*/
+	calc_pll_cs_init_data_hdmi.num_fract_fb_divider_decimal_point =
+			FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;
+	/*number of decimal point to round off for fractional feedback divider value*/
+	calc_pll_cs_init_data_hdmi.num_fract_fb_divider_decimal_point_precision =
+			FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;
+	calc_pll_cs_init_data_hdmi.ctx = ctx;
 
-		/*structure for HDMI, no SS or SS% <= 0.06% for 27 MHz Ref clock */
-		calc_pll_cs_init_data_hdmi.bp = bios;
-		calc_pll_cs_init_data_hdmi.min_pix_clk_pll_post_divider = 1;
-		calc_pll_cs_init_data_hdmi.max_pix_clk_pll_post_divider =
-				clk_src->cs_mask->PLL_POST_DIV_PIXCLK;
-		calc_pll_cs_init_data_hdmi.min_pll_ref_divider = 1;
-		calc_pll_cs_init_data_hdmi.max_pll_ref_divider = clk_src->cs_mask->PLL_REF_DIV;
-		/* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
-		calc_pll_cs_init_data_hdmi.min_override_input_pxl_clk_pll_freq_khz = 13500;
-		/* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
-		calc_pll_cs_init_data_hdmi.max_override_input_pxl_clk_pll_freq_khz = 27000;
-		/*numberOfFractFBDividerDecimalPoints*/
-		calc_pll_cs_init_data_hdmi.num_fract_fb_divider_decimal_point =
-				FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;
-		/*number of decimal point to round off for fractional feedback divider value*/
-		calc_pll_cs_init_data_hdmi.num_fract_fb_divider_decimal_point_precision =
-				FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM;
-		calc_pll_cs_init_data_hdmi.ctx = ctx;
+	clk_src->ref_freq_khz = clk_src->bios->fw_info.pll_info.crystal_frequency;
 
-		clk_src->ref_freq_khz = fw_info.pll_info.crystal_frequency;
+	if (clk_src->base.id == CLOCK_SOURCE_ID_EXTERNAL)
+		return true;
 
-		if (clk_src->base.id == CLOCK_SOURCE_ID_EXTERNAL)
-			return true;
+	/* PLL only from here on */
+	ss_info_from_atombios_create(clk_src);
 
-		/* 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 (!calc_pll_max_vco_construct(
+			&clk_src->calc_pll,
+			&calc_pll_cs_init_data)) {
+		ASSERT_CRITICAL(false);
+		goto unexpected_failure;
+	}
 
 
-		calc_pll_cs_init_data_hdmi.
-				min_override_input_pxl_clk_pll_freq_khz = clk_src->ref_freq_khz/2;
-		calc_pll_cs_init_data_hdmi.
-				max_override_input_pxl_clk_pll_freq_khz = clk_src->ref_freq_khz;
+	calc_pll_cs_init_data_hdmi.
+			min_override_input_pxl_clk_pll_freq_khz = clk_src->ref_freq_khz/2;
+	calc_pll_cs_init_data_hdmi.
+			max_override_input_pxl_clk_pll_freq_khz = clk_src->ref_freq_khz;
 
 
-		if (!calc_pll_max_vco_construct(
-				&clk_src->calc_pll_hdmi, &calc_pll_cs_init_data_hdmi)) {
-			ASSERT_CRITICAL(false);
-			goto unexpected_failure;
-		}
-		break;
-	default:
-		break;
+	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;
@@ -1378,3 +1510,64 @@
 	return false;
 }
 
+bool dce112_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_regs *regs,
+	const struct dce110_clk_src_shift *cs_shift,
+	const struct dce110_clk_src_mask *cs_mask)
+{
+	clk_src->base.ctx = ctx;
+	clk_src->bios = bios;
+	clk_src->base.id = id;
+	clk_src->base.funcs = &dce112_clk_src_funcs;
+
+	clk_src->regs = regs;
+	clk_src->cs_shift = cs_shift;
+	clk_src->cs_mask = cs_mask;
+
+	if (!clk_src->bios->fw_info_valid) {
+		ASSERT_CRITICAL(false);
+		return false;
+	}
+
+	clk_src->ext_clk_khz = clk_src->bios->fw_info.external_clock_source_frequency_for_dp;
+
+	return true;
+}
+
+bool dcn20_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_regs *regs,
+	const struct dce110_clk_src_shift *cs_shift,
+	const struct dce110_clk_src_mask *cs_mask)
+{
+	bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask);
+
+	clk_src->base.funcs = &dcn20_clk_src_funcs;
+
+	return ret;
+}
+
+#if defined(CONFIG_DRM_AMD_DC_DCN3_0)
+bool dcn3_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_regs *regs,
+	const struct dce110_clk_src_shift *cs_shift,
+	const struct dce110_clk_src_mask *cs_mask)
+{
+	bool ret = dce112_clk_src_construct(clk_src, ctx, bios, id, regs, cs_shift, cs_mask);
+
+	clk_src->base.funcs = &dcn3_clk_src_funcs;
+
+	return ret;
+}
+#endif

--
Gitblit v1.6.2