+ u64 datarate = pixel_clock * 10000;
+ u32 ssc_up_spread = 1;
+ u32 mpll_div5_en = 1;
+ u32 hdmi_div = 1;
+ u32 ana_cp_int;
+ u32 ana_cp_prop;
+ u32 refclk_postscalar = refclk >> prescaler_divider;
+ u32 tx_clk_div;
+ u64 vco_clk;
+ u64 vco_clk_do_div;
+ u32 vco_div_refclk_integer;
+ u32 vco_div_refclk_fracn;
+ u32 fracn_quot;
+ u32 fracn_rem;
+ u32 fracn_den;
+ u32 fracn_en;
+ u32 pmix_en;
+ u32 multiplier;
+ int mpll_ana_v2i;
+ int ana_freq_vco = 0;
+ int c, a = 0;
+ int i;
+
+ /* Select appropriate v2i point */
+ if (datarate <= INTEL_SNPS_PHY_HDMI_9999MHZ) {
+ mpll_ana_v2i = 2;
+ tx_clk_div =
ilog2(DIV_ROUND_DOWN_ULL(INTEL_SNPS_PHY_HDMI_9999MHZ,
datarate));
+ } else {
+ mpll_ana_v2i = 3;
+ tx_clk_div =
ilog2(DIV_ROUND_DOWN_ULL(INTEL_SNPS_PHY_HDMI_16GHZ, datarate));
+ }
+ vco_clk = (datarate << tx_clk_div) >> 1;
+
+ vco_div_refclk_integer = DIV_ROUND_DOWN_ULL(vco_clk,
refclk_postscalar);
+ vco_clk_do_div = do_div(vco_clk, refclk_postscalar);
+ vco_div_refclk_fracn = DIV_ROUND_DOWN_ULL(vco_clk_do_div <<
32,
+refclk_postscalar);
+
+ fracn_quot = vco_div_refclk_fracn >> 16;
+ fracn_rem = vco_div_refclk_fracn & 0xffff;
+ fracn_rem = fracn_rem - (fracn_rem >> 15);
+ fracn_den = 0xffff;
+ fracn_en = (fracn_quot != 0 || fracn_rem != 0) ? 1 : 0;
+ pmix_en = fracn_en;
+ multiplier = (vco_div_refclk_integer - 16) * 2;
+ /* Curve selection for ana_cp_* calculations. One curve hardcoded per
v2i range */
+ c = mpll_ana_v2i - 2;
+
+ /* Find the right segment of the table */
+ for (i = 0; i < 8; i += 2) {
+ if (vco_clk <= curve_freq_hz[c][i + 1]) {
+ a = i;
+ ana_freq_vco = 3 - (a >> 1);
+ break;
+ }
+ }
+
+ get_ana_cp_int_prop(vco_clk, refclk_postscalar, mpll_ana_v2i, c, a,
+ curve_freq_hz, curve_0, curve_1, curve_2,
+ &ana_cp_int, &ana_cp_prop);
+
+ pll_params->ssc_up_spread = ssc_up_spread;
+ pll_params->mpll_div5_en = mpll_div5_en;
+ pll_params->hdmi_div = hdmi_div;
+ pll_params->ana_cp_int = ana_cp_int;
+ pll_params->refclk_postscalar = refclk_postscalar;
+ pll_params->tx_clk_div = tx_clk_div;
+ pll_params->fracn_quot = fracn_quot;
+ pll_params->fracn_rem = fracn_rem;
+ pll_params->fracn_den = fracn_den;
+ pll_params->fracn_en = fracn_en;
+ pll_params->pmix_en = pmix_en;
+ pll_params->multiplier = multiplier;
+ pll_params->ana_cp_prop = ana_cp_prop;
+ pll_params->mpll_ana_v2i = mpll_ana_v2i;
+ pll_params->ana_freq_vco = ana_freq_vco; }
+
+void intel_snps_hdmi_pll_compute_mpllb(struct intel_mpllb_state
+*pll_state, u64 pixel_clock) {
+ /* x axis frequencies. One curve in each array per v2i point */
+ static const u64 dg2_curve_freq_hz[2][8] = {
+ { 2500000000ULL, 3000000000ULL, 3000000000ULL,
3500000000ULL, 3500000000ULL,
+ 4000000000ULL, 4000000000ULL, 5000000000ULL },
+ { 4000000000ULL, 4600000000ULL, 4601000000ULL,
5400000000ULL, 5401000000ULL,
+ 6600000000ULL, 6601000000ULL, 8001000000ULL }
+ };
+
+ /* y axis heights multiplied with 1000000000 */
+ static const u64 dg2_curve_0[2][8] = {
+ { 34149871, 39803269, 36034544, 40601014, 35646940,
40016109, 35127987, 41889522 },
+ { 70000000, 78770454, 70451838, 80427119, 70991400,
84230173, 72945921, 87064218 }
+ };
+
+ /* Multiplied with 100 */
+ static const u64 dg2_curve_1[2][8] = {
+ { 85177000000000ULL, 79385227160000ULL,
95672603580000ULL, 88857207160000ULL,
+ 109379790900000ULL, 103528193900000ULL,
131941242400000ULL, 117279000000000ULL },
+ { 60255000000000ULL, 55569000000000ULL,
72036000000000ULL, 69509000000000ULL,
+ 81785000000000ULL, 731030000000000ULL,
96591000000000ULL, 69077000000000ULL }
+ };
+
+ /* Multiplied with 1000000000000 */
+ static const u64 dg2_curve_2[2][8] = {
+ { 2186930000ULL, 2835287134ULL, 2395395343ULL,
2932270687ULL, 2351887545ULL,
+ 2861031697ULL, 2294149152ULL, 3091730000ULL },
+ { 4560000000ULL, 5570000000ULL, 4610000000ULL,
5770000000ULL, 4670000000ULL,
+ 6240000000ULL, 4890000000ULL, 6600000000ULL }
+ };
+
+ struct pll_output_params pll_params;
+ u32 refclk = 100000000;
+ u32 prescaler_divider = 1;
+ u32 ref_range = 3;
+ u32 ana_cp_int_gs = 64;
+ u32 ana_cp_prop_gs = 124;
+
+ compute_hdmi_tmds_pll(pixel_clock, refclk, ref_range, ana_cp_int_gs,
ana_cp_prop_gs,
+ dg2_curve_freq_hz, dg2_curve_0, dg2_curve_1,
dg2_curve_2,
+ prescaler_divider, &pll_params);
+
+ pll_state->clock = pixel_clock;
+ pll_state->ref_control =
+ REG_FIELD_PREP(SNPS_PHY_REF_CONTROL_REF_RANGE,
ref_range);
+ pll_state->mpllb_cp =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT,
pll_params.ana_cp_int) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP,
pll_params.ana_cp_prop) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_INT_GS,
ana_cp_int_gs) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_CP_PROP_GS,
ana_cp_prop_gs);
+ pll_state->mpllb_div =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_DIV5_CLK_EN,
pll_params.mpll_div5_en) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_TX_CLK_DIV,
pll_params.tx_clk_div) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_PMIX_EN,
pll_params.pmix_en) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_V2I,
pll_params.mpll_ana_v2i) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FREQ_VCO,
pll_params.ana_freq_vco);
+ pll_state->mpllb_div2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_REF_CLK_DIV,
prescaler_divider) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_MULTIPLIER,
pll_params.multiplier) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_HDMI_DIV,
pll_params.hdmi_div);
+ pll_state->mpllb_fracn1 =
+
REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_CGG_UPDATE_EN, 1) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_EN,
pll_params.fracn_en) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_DEN,
pll_params.fracn_den);
+ pll_state->mpllb_fracn2 =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_QUOT,
pll_params.fracn_quot) |
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_FRACN_REM,
pll_params.fracn_rem);
+ pll_state->mpllb_sscen =
+ REG_FIELD_PREP(SNPS_PHY_MPLLB_SSC_UP_SPREAD,
+pll_params.ssc_up_spread); }
diff --git a/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.h
b/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.h
new file mode 100644
index 000000000000..37ccf138dbcd
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_snps_hdmi_pll.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2024 Synopsys, Inc., Intel Corporation */
+
+#ifndef __INTEL_SNPS_HDMI_PLL_H__
+#define __INTEL_SNPS_HDMI_PLL_H__
+
+#include <linux/types.h>
+
+struct intel_mpllb_state;
+
+void intel_snps_hdmi_pll_compute_mpllb(struct intel_mpllb_state
+*pll_state, u64 pixel_clock);
+
+#endif /* __INTEL_SNPS_HDMI_PLL_H__ */
diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index
1ff9602a52f6..feabbd476bb1 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -258,6 +258,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \
i915-display/intel_psr.o \
i915-display/intel_qp_tables.o \
i915-display/intel_quirks.o \
+ i915-display/intel_snps_hdmi_pll.o \
i915-display/intel_snps_phy.o \
i915-display/intel_tc.o \
i915-display/intel_vblank.o \
--
2.45.2