xref: /linux/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.c (revision 7abdafd2343ab199367c8243d6a5f06a9aa6976b)
159476420SAnkit Nautiyal // SPDX-License-Identifier: MIT
259476420SAnkit Nautiyal /*
359476420SAnkit Nautiyal  * Copyright © 2025 Synopsys, Inc., Intel Corporation
459476420SAnkit Nautiyal  */
559476420SAnkit Nautiyal 
659476420SAnkit Nautiyal #include <linux/math.h>
759476420SAnkit Nautiyal 
882ecaae2SAnkit Nautiyal #include "intel_cx0_phy_regs.h"
959476420SAnkit Nautiyal #include "intel_display_types.h"
1059476420SAnkit Nautiyal #include "intel_snps_phy.h"
1159476420SAnkit Nautiyal #include "intel_snps_phy_regs.h"
1259476420SAnkit Nautiyal #include "intel_snps_hdmi_pll.h"
1359476420SAnkit Nautiyal 
1459476420SAnkit Nautiyal #define INTEL_SNPS_PHY_HDMI_4999MHZ 4999999900ULL
1559476420SAnkit Nautiyal #define INTEL_SNPS_PHY_HDMI_16GHZ 16000000000ULL
1659476420SAnkit Nautiyal #define INTEL_SNPS_PHY_HDMI_9999MHZ (2 * INTEL_SNPS_PHY_HDMI_4999MHZ)
1759476420SAnkit Nautiyal 
1859476420SAnkit Nautiyal #define CURVE0_MULTIPLIER 1000000000
1959476420SAnkit Nautiyal #define CURVE1_MULTIPLIER 100
2059476420SAnkit Nautiyal #define CURVE2_MULTIPLIER 1000000000000ULL
2159476420SAnkit Nautiyal 
2259476420SAnkit Nautiyal struct pll_output_params {
2359476420SAnkit Nautiyal 	u32 ssc_up_spread;
2459476420SAnkit Nautiyal 	u32 mpll_div5_en;
2559476420SAnkit Nautiyal 	u32 hdmi_div;
2659476420SAnkit Nautiyal 	u32 ana_cp_int;
2759476420SAnkit Nautiyal 	u32 ana_cp_prop;
2859476420SAnkit Nautiyal 	u32 refclk_postscalar;
2959476420SAnkit Nautiyal 	u32 tx_clk_div;
3059476420SAnkit Nautiyal 	u32 fracn_quot;
3159476420SAnkit Nautiyal 	u32 fracn_rem;
3259476420SAnkit Nautiyal 	u32 fracn_den;
3359476420SAnkit Nautiyal 	u32 fracn_en;
3459476420SAnkit Nautiyal 	u32 pmix_en;
3559476420SAnkit Nautiyal 	u32 multiplier;
3659476420SAnkit Nautiyal 	int mpll_ana_v2i;
3759476420SAnkit Nautiyal 	int ana_freq_vco;
3859476420SAnkit Nautiyal };
3959476420SAnkit Nautiyal 
interp(s64 x,s64 x1,s64 x2,s64 y1,s64 y2)4059476420SAnkit Nautiyal static s64 interp(s64 x, s64 x1, s64 x2, s64 y1, s64 y2)
4159476420SAnkit Nautiyal {
4259476420SAnkit Nautiyal 	s64 dydx;
4359476420SAnkit Nautiyal 
44791d7600SDibin Moolakadan Subrahmanian 	dydx = DIV64_U64_ROUND_UP((y2 - y1) * 100000, (x2 - x1));
4559476420SAnkit Nautiyal 
46791d7600SDibin Moolakadan Subrahmanian 	return (y1 + DIV64_U64_ROUND_UP(dydx * (x - x1), 100000));
4759476420SAnkit Nautiyal }
4859476420SAnkit Nautiyal 
get_ana_cp_int_prop(u64 vco_clk,u32 refclk_postscalar,int mpll_ana_v2i,int c,int a,const u64 curve_freq_hz[2][8],const u64 curve_0[2][8],const u64 curve_1[2][8],const u64 curve_2[2][8],u32 * ana_cp_int,u32 * ana_cp_prop)49791d7600SDibin Moolakadan Subrahmanian static void get_ana_cp_int_prop(u64 vco_clk,
5059476420SAnkit Nautiyal 				u32 refclk_postscalar,
5159476420SAnkit Nautiyal 				int mpll_ana_v2i,
5259476420SAnkit Nautiyal 				int c, int a,
5359476420SAnkit Nautiyal 				const u64 curve_freq_hz[2][8],
5459476420SAnkit Nautiyal 				const u64 curve_0[2][8],
5559476420SAnkit Nautiyal 				const u64 curve_1[2][8],
5659476420SAnkit Nautiyal 				const u64 curve_2[2][8],
5759476420SAnkit Nautiyal 				u32 *ana_cp_int,
5859476420SAnkit Nautiyal 				u32 *ana_cp_prop)
5959476420SAnkit Nautiyal {
6059476420SAnkit Nautiyal 	u64 vco_div_refclk_float;
6159476420SAnkit Nautiyal 	u64 curve_0_interpolated;
6259476420SAnkit Nautiyal 	u64 curve_2_interpolated;
6359476420SAnkit Nautiyal 	u64 curve_1_interpolated;
6459476420SAnkit Nautiyal 	u64 curve_2_scaled1;
6559476420SAnkit Nautiyal 	u64 curve_2_scaled2;
6659476420SAnkit Nautiyal 	u64 adjusted_vco_clk1;
6759476420SAnkit Nautiyal 	u64 adjusted_vco_clk2;
6859476420SAnkit Nautiyal 	u64 curve_2_scaled_int;
6959476420SAnkit Nautiyal 	u64 interpolated_product;
7059476420SAnkit Nautiyal 	u64 scaled_interpolated_sqrt;
7159476420SAnkit Nautiyal 	u64 scaled_vco_div_refclk1;
7259476420SAnkit Nautiyal 	u64 scaled_vco_div_refclk2;
7359476420SAnkit Nautiyal 	u64 ana_cp_int_temp;
7459476420SAnkit Nautiyal 	u64 temp;
7559476420SAnkit Nautiyal 
7659476420SAnkit Nautiyal 	vco_div_refclk_float = vco_clk * DIV_ROUND_DOWN_ULL(1000000000000ULL, refclk_postscalar);
7759476420SAnkit Nautiyal 
7859476420SAnkit Nautiyal 	/* Interpolate curve values at the target vco_clk frequency */
7959476420SAnkit Nautiyal 	curve_0_interpolated = interp(vco_clk, curve_freq_hz[c][a], curve_freq_hz[c][a + 1],
8059476420SAnkit Nautiyal 				      curve_0[c][a], curve_0[c][a + 1]);
8159476420SAnkit Nautiyal 
8259476420SAnkit Nautiyal 	curve_2_interpolated = interp(vco_clk, curve_freq_hz[c][a], curve_freq_hz[c][a + 1],
8359476420SAnkit Nautiyal 				      curve_2[c][a], curve_2[c][a + 1]);
8459476420SAnkit Nautiyal 
8559476420SAnkit Nautiyal 	curve_1_interpolated = interp(vco_clk, curve_freq_hz[c][a], curve_freq_hz[c][a + 1],
8659476420SAnkit Nautiyal 				      curve_1[c][a], curve_1[c][a + 1]);
8759476420SAnkit Nautiyal 
8859476420SAnkit Nautiyal 	curve_1_interpolated = DIV_ROUND_DOWN_ULL(curve_1_interpolated, CURVE1_MULTIPLIER);
8959476420SAnkit Nautiyal 
9059476420SAnkit Nautiyal 	/*
9159476420SAnkit Nautiyal 	 * Scale curve_2_interpolated based on mpll_ana_v2i, for integer part
9259476420SAnkit Nautiyal 	 * ana_cp_int and for the proportional part ana_cp_prop
9359476420SAnkit Nautiyal 	 */
9459476420SAnkit Nautiyal 	temp = curve_2_interpolated * (4 - mpll_ana_v2i);
9559476420SAnkit Nautiyal 	curve_2_scaled1 = DIV_ROUND_DOWN_ULL(temp, 16000);
9659476420SAnkit Nautiyal 	curve_2_scaled2 = DIV_ROUND_DOWN_ULL(temp, 160);
9759476420SAnkit Nautiyal 
9859476420SAnkit Nautiyal 	/* Scale vco_div_refclk for ana_cp_int */
9959476420SAnkit Nautiyal 	scaled_vco_div_refclk1 = 112008301 * DIV_ROUND_DOWN_ULL(vco_div_refclk_float, 100000);
10059476420SAnkit Nautiyal 
10159476420SAnkit Nautiyal 	adjusted_vco_clk1 = CURVE2_MULTIPLIER *
10259476420SAnkit Nautiyal 			    DIV_ROUND_DOWN_ULL(scaled_vco_div_refclk1, (curve_0_interpolated *
10359476420SAnkit Nautiyal 			    DIV_ROUND_DOWN_ULL(curve_1_interpolated, CURVE0_MULTIPLIER)));
10459476420SAnkit Nautiyal 
10559476420SAnkit Nautiyal 	ana_cp_int_temp =
106*9205999eSAnkit Nautiyal 		DIV64_U64_ROUND_CLOSEST(DIV_ROUND_DOWN_ULL(adjusted_vco_clk1, curve_2_scaled1),
10759476420SAnkit Nautiyal 					CURVE2_MULTIPLIER);
10859476420SAnkit Nautiyal 
10959476420SAnkit Nautiyal 	*ana_cp_int = max(1, min(ana_cp_int_temp, 127));
11059476420SAnkit Nautiyal 
11159476420SAnkit Nautiyal 	curve_2_scaled_int = curve_2_scaled1 * (*ana_cp_int);
11259476420SAnkit Nautiyal 
11359476420SAnkit Nautiyal 	interpolated_product = curve_1_interpolated *
11459476420SAnkit Nautiyal 			       (curve_2_scaled_int * DIV_ROUND_DOWN_ULL(curve_0_interpolated,
11559476420SAnkit Nautiyal 								      CURVE0_MULTIPLIER));
11659476420SAnkit Nautiyal 
11759476420SAnkit Nautiyal 	scaled_interpolated_sqrt =
118791d7600SDibin Moolakadan Subrahmanian 			int_sqrt(DIV64_U64_ROUND_UP(interpolated_product, vco_div_refclk_float) *
11959476420SAnkit Nautiyal 			DIV_ROUND_DOWN_ULL(1000000000000ULL, 55));
12059476420SAnkit Nautiyal 
12159476420SAnkit Nautiyal 	/* Scale vco_div_refclk for ana_cp_int */
12259476420SAnkit Nautiyal 	scaled_vco_div_refclk2 = DIV_ROUND_UP_ULL(vco_div_refclk_float, 1000000);
123791d7600SDibin Moolakadan Subrahmanian 	adjusted_vco_clk2 = 1460281 * DIV64_U64_ROUND_UP(scaled_interpolated_sqrt *
12459476420SAnkit Nautiyal 						       scaled_vco_div_refclk2,
12559476420SAnkit Nautiyal 						       curve_1_interpolated);
12659476420SAnkit Nautiyal 
127791d7600SDibin Moolakadan Subrahmanian 	*ana_cp_prop = DIV64_U64_ROUND_UP(adjusted_vco_clk2, curve_2_scaled2);
12859476420SAnkit Nautiyal 	*ana_cp_prop = max(1, min(*ana_cp_prop, 127));
12959476420SAnkit Nautiyal }
13059476420SAnkit Nautiyal 
compute_hdmi_tmds_pll(u64 pixel_clock,u32 refclk,u32 ref_range,u32 ana_cp_int_gs,u32 ana_cp_prop_gs,const u64 curve_freq_hz[2][8],const u64 curve_0[2][8],const u64 curve_1[2][8],const u64 curve_2[2][8],u32 prescaler_divider,struct pll_output_params * pll_params)13159476420SAnkit Nautiyal static void compute_hdmi_tmds_pll(u64 pixel_clock, u32 refclk,
13259476420SAnkit Nautiyal 				  u32 ref_range,
13359476420SAnkit Nautiyal 				  u32 ana_cp_int_gs,
13459476420SAnkit Nautiyal 				  u32 ana_cp_prop_gs,
13559476420SAnkit Nautiyal 				  const u64 curve_freq_hz[2][8],
13659476420SAnkit Nautiyal 				  const u64 curve_0[2][8],
13759476420SAnkit Nautiyal 				  const u64 curve_1[2][8],
13859476420SAnkit Nautiyal 				  const u64 curve_2[2][8],
13959476420SAnkit Nautiyal 				  u32 prescaler_divider,
14059476420SAnkit Nautiyal 				  struct pll_output_params *pll_params)
14159476420SAnkit Nautiyal {
14259476420SAnkit Nautiyal 	u64 datarate = pixel_clock * 10000;
14359476420SAnkit Nautiyal 	u32 ssc_up_spread = 1;
14459476420SAnkit Nautiyal 	u32 mpll_div5_en = 1;
14559476420SAnkit Nautiyal 	u32 hdmi_div = 1;
14659476420SAnkit Nautiyal 	u32 ana_cp_int;
14759476420SAnkit Nautiyal 	u32 ana_cp_prop;
14859476420SAnkit Nautiyal 	u32 refclk_postscalar = refclk >> prescaler_divider;
14959476420SAnkit Nautiyal 	u32 tx_clk_div;
15059476420SAnkit Nautiyal 	u64 vco_clk;
15159476420SAnkit Nautiyal 	u64 vco_clk_do_div;
15259476420SAnkit Nautiyal 	u32 vco_div_refclk_integer;
15359476420SAnkit Nautiyal 	u32 vco_div_refclk_fracn;
15459476420SAnkit Nautiyal 	u32 fracn_quot;
15559476420SAnkit Nautiyal 	u32 fracn_rem;
15659476420SAnkit Nautiyal 	u32 fracn_den;
15759476420SAnkit Nautiyal 	u32 fracn_en;
15859476420SAnkit Nautiyal 	u32 pmix_en;
15959476420SAnkit Nautiyal 	u32 multiplier;
16059476420SAnkit Nautiyal 	int mpll_ana_v2i;
16159476420SAnkit Nautiyal 	int ana_freq_vco = 0;
16259476420SAnkit Nautiyal 	int c, a = 0;
16359476420SAnkit Nautiyal 	int i;
16459476420SAnkit Nautiyal 
16559476420SAnkit Nautiyal 	/* Select appropriate v2i point */
16659476420SAnkit Nautiyal 	if (datarate <= INTEL_SNPS_PHY_HDMI_9999MHZ) {
16759476420SAnkit Nautiyal 		mpll_ana_v2i = 2;
168791d7600SDibin Moolakadan Subrahmanian 		tx_clk_div = ilog2(div64_u64(INTEL_SNPS_PHY_HDMI_9999MHZ, datarate));
16959476420SAnkit Nautiyal 	} else {
17059476420SAnkit Nautiyal 		mpll_ana_v2i = 3;
171791d7600SDibin Moolakadan Subrahmanian 		tx_clk_div = ilog2(div64_u64(INTEL_SNPS_PHY_HDMI_16GHZ, datarate));
17259476420SAnkit Nautiyal 	}
17359476420SAnkit Nautiyal 	vco_clk = (datarate << tx_clk_div) >> 1;
17459476420SAnkit Nautiyal 
17559476420SAnkit Nautiyal 	vco_div_refclk_integer = DIV_ROUND_DOWN_ULL(vco_clk, refclk_postscalar);
17659476420SAnkit Nautiyal 	vco_clk_do_div = do_div(vco_clk, refclk_postscalar);
17759476420SAnkit Nautiyal 	vco_div_refclk_fracn = DIV_ROUND_DOWN_ULL(vco_clk_do_div << 32, refclk_postscalar);
17859476420SAnkit Nautiyal 
17959476420SAnkit Nautiyal 	fracn_quot = vco_div_refclk_fracn >> 16;
18059476420SAnkit Nautiyal 	fracn_rem = vco_div_refclk_fracn & 0xffff;
18159476420SAnkit Nautiyal 	fracn_rem = fracn_rem - (fracn_rem >> 15);
18259476420SAnkit Nautiyal 	fracn_den = 0xffff;
18359476420SAnkit Nautiyal 	fracn_en = (fracn_quot != 0 || fracn_rem != 0) ? 1 : 0;
18459476420SAnkit Nautiyal 	pmix_en = fracn_en;
18559476420SAnkit Nautiyal 	multiplier = (vco_div_refclk_integer - 16) * 2;
18659476420SAnkit Nautiyal 	/* Curve selection for ana_cp_* calculations. One curve hardcoded per v2i range */
18759476420SAnkit Nautiyal 	c = mpll_ana_v2i - 2;
18859476420SAnkit Nautiyal 
18959476420SAnkit Nautiyal 	/* Find the right segment of the table */
19059476420SAnkit Nautiyal 	for (i = 0; i < 8; i += 2) {
19159476420SAnkit Nautiyal 		if (vco_clk <= curve_freq_hz[c][i + 1]) {
19259476420SAnkit Nautiyal 			a = i;
19359476420SAnkit Nautiyal 			ana_freq_vco = 3 - (a >> 1);
19459476420SAnkit Nautiyal 			break;
19559476420SAnkit Nautiyal 		}
19659476420SAnkit Nautiyal 	}
19759476420SAnkit Nautiyal 
19859476420SAnkit Nautiyal 	get_ana_cp_int_prop(vco_clk, refclk_postscalar, mpll_ana_v2i, c, a,
19959476420SAnkit Nautiyal 			    curve_freq_hz, curve_0, curve_1, curve_2,
20059476420SAnkit Nautiyal 			    &ana_cp_int, &ana_cp_prop);
20159476420SAnkit Nautiyal 
20259476420SAnkit Nautiyal 	pll_params->ssc_up_spread = ssc_up_spread;
20359476420SAnkit Nautiyal 	pll_params->mpll_div5_en = mpll_div5_en;
20459476420SAnkit Nautiyal 	pll_params->hdmi_div = hdmi_div;
20559476420SAnkit Nautiyal 	pll_params->ana_cp_int = ana_cp_int;
20659476420SAnkit Nautiyal 	pll_params->refclk_postscalar = refclk_postscalar;
20759476420SAnkit Nautiyal 	pll_params->tx_clk_div = tx_clk_div;
20859476420SAnkit Nautiyal 	pll_params->fracn_quot = fracn_quot;
20959476420SAnkit Nautiyal 	pll_params->fracn_rem = fracn_rem;
21059476420SAnkit Nautiyal 	pll_params->fracn_den = fracn_den;
21159476420SAnkit Nautiyal 	pll_params->fracn_en = fracn_en;
21259476420SAnkit Nautiyal 	pll_params->pmix_en = pmix_en;
21359476420SAnkit Nautiyal 	pll_params->multiplier = multiplier;
21459476420SAnkit Nautiyal 	pll_params->ana_cp_prop = ana_cp_prop;
21559476420SAnkit Nautiyal 	pll_params->mpll_ana_v2i = mpll_ana_v2i;
21659476420SAnkit Nautiyal 	pll_params->ana_freq_vco = ana_freq_vco;
21759476420SAnkit Nautiyal }
21859476420SAnkit Nautiyal 
intel_snps_hdmi_pll_compute_mpllb(struct intel_mpllb_state * pll_state,u64 pixel_clock)21959476420SAnkit Nautiyal void intel_snps_hdmi_pll_compute_mpllb(struct intel_mpllb_state *pll_state, u64 pixel_clock)
22059476420SAnkit Nautiyal {
22159476420SAnkit Nautiyal 	/* x axis frequencies. One curve in each array per v2i point */
22259476420SAnkit Nautiyal 	static const u64 dg2_curve_freq_hz[2][8] = {
22359476420SAnkit Nautiyal 		{ 2500000000ULL, 3000000000ULL, 3000000000ULL, 3500000000ULL, 3500000000ULL,
22459476420SAnkit Nautiyal 		  4000000000ULL, 4000000000ULL, 5000000000ULL },
22559476420SAnkit Nautiyal 		{ 4000000000ULL, 4600000000ULL, 4601000000ULL, 5400000000ULL, 5401000000ULL,
22659476420SAnkit Nautiyal 		  6600000000ULL, 6601000000ULL, 8001000000ULL }
22759476420SAnkit Nautiyal 	};
22859476420SAnkit Nautiyal 
22959476420SAnkit Nautiyal 	/* y axis heights multiplied with 1000000000 */
23059476420SAnkit Nautiyal 	static const u64 dg2_curve_0[2][8] = {
23159476420SAnkit Nautiyal 		{ 34149871, 39803269, 36034544, 40601014, 35646940, 40016109, 35127987, 41889522 },
23259476420SAnkit Nautiyal 		{ 70000000, 78770454, 70451838, 80427119, 70991400, 84230173, 72945921, 87064218 }
23359476420SAnkit Nautiyal 	};
23459476420SAnkit Nautiyal 
23559476420SAnkit Nautiyal 	/* Multiplied with 100 */
23659476420SAnkit Nautiyal 	static const u64 dg2_curve_1[2][8] = {
23759476420SAnkit Nautiyal 		{ 85177000000000ULL, 79385227160000ULL, 95672603580000ULL, 88857207160000ULL,
23859476420SAnkit Nautiyal 		  109379790900000ULL, 103528193900000ULL, 131941242400000ULL, 117279000000000ULL },
23959476420SAnkit Nautiyal 		{ 60255000000000ULL, 55569000000000ULL, 72036000000000ULL, 69509000000000ULL,
24059476420SAnkit Nautiyal 		  81785000000000ULL, 731030000000000ULL, 96591000000000ULL, 69077000000000ULL }
24159476420SAnkit Nautiyal 	};
24259476420SAnkit Nautiyal 
24359476420SAnkit Nautiyal 	/* Multiplied with 1000000000000 */
24459476420SAnkit Nautiyal 	static const u64 dg2_curve_2[2][8] = {
24559476420SAnkit Nautiyal 		{ 2186930000ULL, 2835287134ULL, 2395395343ULL, 2932270687ULL, 2351887545ULL,
24659476420SAnkit Nautiyal 		  2861031697ULL, 2294149152ULL, 3091730000ULL },
24759476420SAnkit Nautiyal 		{ 4560000000ULL, 5570000000ULL, 4610000000ULL, 5770000000ULL, 4670000000ULL,
24859476420SAnkit Nautiyal 		  6240000000ULL, 4890000000ULL, 6600000000ULL }
24959476420SAnkit Nautiyal 	};
25059476420SAnkit Nautiyal 
25159476420SAnkit Nautiyal 	struct pll_output_params pll_params;
25259476420SAnkit Nautiyal 	u32 refclk = 100000000;
25359476420SAnkit Nautiyal 	u32 prescaler_divider = 1;
25459476420SAnkit Nautiyal 	u32 ref_range = 3;
25559476420SAnkit Nautiyal 	u32 ana_cp_int_gs = 64;
25659476420SAnkit Nautiyal 	u32 ana_cp_prop_gs = 124;
25759476420SAnkit Nautiyal 
25859476420SAnkit Nautiyal 	compute_hdmi_tmds_pll(pixel_clock, refclk, ref_range, ana_cp_int_gs, ana_cp_prop_gs,
25959476420SAnkit Nautiyal 			      dg2_curve_freq_hz, dg2_curve_0, dg2_curve_1, dg2_curve_2,
26059476420SAnkit Nautiyal 			      prescaler_divider, &pll_params);
26159476420SAnkit Nautiyal 
26259476420SAnkit Nautiyal 	pll_state->clock = pixel_clock;
26359476420SAnkit Nautiyal 	pll_state->ref_control =
26459476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE, ref_range);
26559476420SAnkit Nautiyal 	pll_state->mpllb_cp =
26659476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT, pll_params.ana_cp_int) |
26759476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP, pll_params.ana_cp_prop) |
26859476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS, ana_cp_int_gs) |
26959476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS, ana_cp_prop_gs);
27059476420SAnkit Nautiyal 	pll_state->mpllb_div =
27159476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN, pll_params.mpll_div5_en) |
27259476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV, pll_params.tx_clk_div) |
27359476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN, pll_params.pmix_en) |
27459476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I, pll_params.mpll_ana_v2i) |
27559476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO, pll_params.ana_freq_vco);
27659476420SAnkit Nautiyal 	pll_state->mpllb_div2 =
27759476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV, prescaler_divider) |
27859476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER, pll_params.multiplier) |
27959476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV, pll_params.hdmi_div);
28059476420SAnkit Nautiyal 	pll_state->mpllb_fracn1 =
28159476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
28259476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN, pll_params.fracn_en) |
28359476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN, pll_params.fracn_den);
28459476420SAnkit Nautiyal 	pll_state->mpllb_fracn2 =
28559476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT, pll_params.fracn_quot) |
28659476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM, pll_params.fracn_rem);
28759476420SAnkit Nautiyal 	pll_state->mpllb_sscen =
28859476420SAnkit Nautiyal 		REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD, pll_params.ssc_up_spread);
28959476420SAnkit Nautiyal }
29082ecaae2SAnkit Nautiyal 
intel_snps_hdmi_pll_compute_c10pll(struct intel_c10pll_state * pll_state,u64 pixel_clock)29182ecaae2SAnkit Nautiyal void intel_snps_hdmi_pll_compute_c10pll(struct intel_c10pll_state *pll_state, u64 pixel_clock)
29282ecaae2SAnkit Nautiyal {
29382ecaae2SAnkit Nautiyal 	/* x axis frequencies. One curve in each array per v2i point */
29482ecaae2SAnkit Nautiyal 	static const u64 c10_curve_freq_hz[2][8] = {
29582ecaae2SAnkit Nautiyal 		{ 2500000000ULL, 3000000000ULL, 3000000000ULL, 3500000000ULL, 3500000000ULL,
29682ecaae2SAnkit Nautiyal 		  4000000000ULL, 4000000000ULL, 5000000000ULL },
29782ecaae2SAnkit Nautiyal 		{ 4000000000ULL, 4600000000ULL, 4601000000ULL, 5400000000ULL, 5401000000ULL,
29882ecaae2SAnkit Nautiyal 		  6600000000ULL, 6601000000ULL, 8001000000ULL }
29982ecaae2SAnkit Nautiyal 	};
30082ecaae2SAnkit Nautiyal 
30182ecaae2SAnkit Nautiyal 	/* y axis heights multiplied with 1000000000 */
30282ecaae2SAnkit Nautiyal 	static const u64 c10_curve_0[2][8] = {
30382ecaae2SAnkit Nautiyal 		{ 41174500, 48605500, 42973700, 49433100, 42408600, 47681900, 40297400, 49131400 },
30482ecaae2SAnkit Nautiyal 		{ 82056800, 94420700, 82323400, 96370600, 81273300, 98630100, 81728700, 99105700}
30582ecaae2SAnkit Nautiyal 	};
30682ecaae2SAnkit Nautiyal 
30782ecaae2SAnkit Nautiyal 	static const u64 c10_curve_1[2][8] = {
30882ecaae2SAnkit Nautiyal 		{ 73300000000000ULL, 66000000000000ULL, 83100000000000ULL, 75300000000000ULL,
30982ecaae2SAnkit Nautiyal 		  99700000000000ULL, 92300000000000ULL, 125000000000000ULL, 110000000000000ULL },
31082ecaae2SAnkit Nautiyal 		{ 53700000000000ULL, 47700000000000ULL, 62200000000000ULL, 54400000000000ULL,
31182ecaae2SAnkit Nautiyal 		  75100000000000ULL, 63400000000000ULL, 90600000000000ULL, 76300000000000ULL }
31282ecaae2SAnkit Nautiyal 	};
31382ecaae2SAnkit Nautiyal 
31482ecaae2SAnkit Nautiyal 	/* Multiplied with 1000000000000 */
31582ecaae2SAnkit Nautiyal 	static const u64 c10_curve_2[2][8] = {
31682ecaae2SAnkit Nautiyal 		{ 2415790000ULL, 3136460000ULL, 2581990000ULL, 3222670000ULL, 2529330000ULL,
31782ecaae2SAnkit Nautiyal 		  3042020000ULL, 2336970000ULL, 3191460000ULL},
31882ecaae2SAnkit Nautiyal 		{ 4808390000ULL, 5994250000ULL, 4832730000ULL, 6193730000ULL, 4737700000ULL,
31982ecaae2SAnkit Nautiyal 		  6428750000ULL, 4779200000ULL, 6479340000ULL }
32082ecaae2SAnkit Nautiyal 	};
32182ecaae2SAnkit Nautiyal 
32282ecaae2SAnkit Nautiyal 	struct pll_output_params pll_params;
32382ecaae2SAnkit Nautiyal 	u32 refclk = 38400000;
32482ecaae2SAnkit Nautiyal 	u32 prescaler_divider = 0;
32582ecaae2SAnkit Nautiyal 	u32 ref_range = 1;
32682ecaae2SAnkit Nautiyal 	u32 ana_cp_int_gs = 30;
32782ecaae2SAnkit Nautiyal 	u32 ana_cp_prop_gs = 28;
32882ecaae2SAnkit Nautiyal 
32982ecaae2SAnkit Nautiyal 	compute_hdmi_tmds_pll(pixel_clock, refclk, ref_range,
33082ecaae2SAnkit Nautiyal 			      ana_cp_int_gs, ana_cp_prop_gs,
33182ecaae2SAnkit Nautiyal 			      c10_curve_freq_hz, c10_curve_0,
33282ecaae2SAnkit Nautiyal 			      c10_curve_1, c10_curve_2, prescaler_divider,
33382ecaae2SAnkit Nautiyal 			      &pll_params);
33482ecaae2SAnkit Nautiyal 
33582ecaae2SAnkit Nautiyal 	pll_state->tx = 0x10;
33682ecaae2SAnkit Nautiyal 	pll_state->cmn = 0x1;
33782ecaae2SAnkit Nautiyal 	pll_state->pll[0] = REG_FIELD_PREP(C10_PLL0_DIV5CLK_EN, pll_params.mpll_div5_en) |
33882ecaae2SAnkit Nautiyal 			    REG_FIELD_PREP(C10_PLL0_FRACEN, pll_params.fracn_en) |
33982ecaae2SAnkit Nautiyal 			    REG_FIELD_PREP(C10_PLL0_PMIX_EN, pll_params.pmix_en) |
34082ecaae2SAnkit Nautiyal 			    REG_FIELD_PREP(C10_PLL0_ANA_FREQ_VCO_MASK, pll_params.ana_freq_vco);
34182ecaae2SAnkit Nautiyal 	pll_state->pll[2] = REG_FIELD_PREP(C10_PLL2_MULTIPLIERL_MASK, pll_params.multiplier);
34282ecaae2SAnkit Nautiyal 	pll_state->pll[3] = REG_FIELD_PREP(C10_PLL3_MULTIPLIERH_MASK, pll_params.multiplier >> 8);
34382ecaae2SAnkit Nautiyal 	pll_state->pll[8] = REG_FIELD_PREP(C10_PLL8_SSC_UP_SPREAD, pll_params.ssc_up_spread);
34482ecaae2SAnkit Nautiyal 	pll_state->pll[9] = REG_FIELD_PREP(C10_PLL9_FRACN_DENL_MASK, pll_params.fracn_den);
34582ecaae2SAnkit Nautiyal 	pll_state->pll[10] = REG_FIELD_PREP(C10_PLL10_FRACN_DENH_MASK, pll_params.fracn_den >> 8);
34682ecaae2SAnkit Nautiyal 	pll_state->pll[11] = REG_FIELD_PREP(C10_PLL11_FRACN_QUOT_L_MASK, pll_params.fracn_quot);
34782ecaae2SAnkit Nautiyal 	pll_state->pll[12] = REG_FIELD_PREP(C10_PLL12_FRACN_QUOT_H_MASK,
34882ecaae2SAnkit Nautiyal 					    pll_params.fracn_quot >> 8);
34982ecaae2SAnkit Nautiyal 
35082ecaae2SAnkit Nautiyal 	pll_state->pll[13] = REG_FIELD_PREP(C10_PLL13_FRACN_REM_L_MASK, pll_params.fracn_rem);
35182ecaae2SAnkit Nautiyal 	pll_state->pll[14] = REG_FIELD_PREP(C10_PLL14_FRACN_REM_H_MASK, pll_params.fracn_rem >> 8);
35282ecaae2SAnkit Nautiyal 	pll_state->pll[15] = REG_FIELD_PREP(C10_PLL15_TXCLKDIV_MASK, pll_params.tx_clk_div) |
35382ecaae2SAnkit Nautiyal 			     REG_FIELD_PREP(C10_PLL15_HDMIDIV_MASK, pll_params.hdmi_div);
35482ecaae2SAnkit Nautiyal 	pll_state->pll[16] = REG_FIELD_PREP(C10_PLL16_ANA_CPINT, pll_params.ana_cp_int) |
35582ecaae2SAnkit Nautiyal 			     REG_FIELD_PREP(C10_PLL16_ANA_CPINTGS_L, ana_cp_int_gs);
35682ecaae2SAnkit Nautiyal 	pll_state->pll[17] = REG_FIELD_PREP(C10_PLL17_ANA_CPINTGS_H_MASK, ana_cp_int_gs >> 1) |
35782ecaae2SAnkit Nautiyal 			     REG_FIELD_PREP(C10_PLL17_ANA_CPPROP_L_MASK, pll_params.ana_cp_prop);
35882ecaae2SAnkit Nautiyal 	pll_state->pll[18] =
35982ecaae2SAnkit Nautiyal 			REG_FIELD_PREP(C10_PLL18_ANA_CPPROP_H_MASK, pll_params.ana_cp_prop >> 2) |
36082ecaae2SAnkit Nautiyal 			REG_FIELD_PREP(C10_PLL18_ANA_CPPROPGS_L_MASK, ana_cp_prop_gs);
36182ecaae2SAnkit Nautiyal 
36282ecaae2SAnkit Nautiyal 	pll_state->pll[19] = REG_FIELD_PREP(C10_PLL19_ANA_CPPROPGS_H_MASK, ana_cp_prop_gs >> 3) |
36382ecaae2SAnkit Nautiyal 			     REG_FIELD_PREP(C10_PLL19_ANA_V2I_MASK, pll_params.mpll_ana_v2i);
36482ecaae2SAnkit Nautiyal }
365