[prev in list] [next in list] [prev in thread] [next in thread] 

List:       haiku-commits
Subject:    [haiku-commits] haiku: hrev55666 - src/add-ons/accelerants/intel_extreme headers/private/graphics/in
From:       Rudolf Cornelissen <rudhaiku () gmail ! com>
Date:       2021-11-25 20:42:03
Message-ID: 20211125204203.0EE9D3F989 () turing ! freelists ! org
[Download RAW message or body]

hrev55666 adds 1 changeset to branch 'master'
old head: 4500c381d286a19b5ee1cf1196fca135c5fe1d0d
new head: 39e05c7d01484d9aed5438f0b4fef70f4f4728ff
overview: https://git.haiku-os.org/haiku/log/?qt=range&q=39e05c7d0148+%5E4500c381d286

----------------------------------------------------------------------------

39e05c7d0148: intel_extreme: skylake PLL works, all outputs fully functional.

                                 [ Rudolf Cornelissen <rudhaiku@gmail.com> ]

----------------------------------------------------------------------------

Revision:    hrev55666
Commit:      39e05c7d01484d9aed5438f0b4fef70f4f4728ff
URL:         https://git.haiku-os.org/haiku/commit/?id=39e05c7d0148
Author:      Rudolf Cornelissen <rudhaiku@gmail.com>
Date:        Thu Nov 25 22:41:48 2021 UTC

----------------------------------------------------------------------------

6 files changed, 112 insertions(+), 28 deletions(-)
.../graphics/intel_extreme/intel_extreme.h       |  9 +++
src/add-ons/accelerants/intel_extreme/Pipes.cpp  | 67 +++++++++++++++++++-
src/add-ons/accelerants/intel_extreme/Pipes.h    |  2 +-
src/add-ons/accelerants/intel_extreme/Ports.cpp  | 16 ++---
src/add-ons/accelerants/intel_extreme/Ports.h    |  9 ---
src/add-ons/accelerants/intel_extreme/pll.cpp    | 37 +++++++++--

----------------------------------------------------------------------------

diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h \
b/headers/private/graphics/intel_extreme/intel_extreme.h index 71ad2b0330..c210dd4044 \
                100644
--- a/headers/private/graphics/intel_extreme/intel_extreme.h
+++ b/headers/private/graphics/intel_extreme/intel_extreme.h
@@ -212,6 +212,15 @@ struct DeviceType {
 	}
 };
 
+enum port_index {
+	INTEL_PORT_ANY,				// wildcard for lookup functions
+	INTEL_PORT_A,
+	INTEL_PORT_B,
+	INTEL_PORT_C,
+	INTEL_PORT_D,
+	INTEL_PORT_E
+};
+
 enum pch_info {
 	INTEL_PCH_NONE = 0,		// No PCH present
 	INTEL_PCH_IBX,			// Ibexpeak
diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.cpp \
b/src/add-ons/accelerants/intel_extreme/Pipes.cpp index 08280b7194..e1f3b4c4a0 100644
--- a/src/add-ons/accelerants/intel_extreme/Pipes.cpp
+++ b/src/add-ons/accelerants/intel_extreme/Pipes.cpp
@@ -463,10 +463,75 @@ Pipe::ConfigureClocks(const pll_divisors& divisors, uint32 \
pixelClock,  
 void
 Pipe::ConfigureClocksSKL(const skl_wrpll_params& wrpll_params, uint32 pixelClock,
-	uint32 extraFlags)
+	port_index pllForPort)
 {
 	CALLED();
 
+	//find our PLL as set by the BIOS
+	uint32 portSel = read32(SKL_DPLL_CTRL2);
+	uint32 pllSel = 0;
+	switch (pllForPort) {
+	case INTEL_PORT_A:
+		pllSel = (portSel & 0x0006) >> 1;
+		break;
+	case INTEL_PORT_B:
+		pllSel = (portSel & 0x0030) >> 4;
+		break;
+	case INTEL_PORT_C:
+		pllSel = (portSel & 0x0180) >> 7;
+		break;
+	case INTEL_PORT_D:
+		pllSel = (portSel & 0x0c00) >> 10;
+		break;
+	case INTEL_PORT_E:
+		pllSel = (portSel & 0x6000) >> 13;
+		break;
+	default:
+		TRACE("No port selected!");
+		return;
+	}
+	TRACE("PLL selected is %" B_PRIx32 "\n", pllSel);
+
+	TRACE("Skylake DPLL_CFGCR1 0x%" B_PRIx32 "\n",
+		read32(SKL_DPLL1_CFGCR1 + (pllSel - 1) * 8));
+	TRACE("Skylake DPLL_CFGCR2 0x%" B_PRIx32 "\n",
+		read32(SKL_DPLL1_CFGCR2 + (pllSel - 1) * 8));
+
+	// only program PLL's that are in non-DP mode (otherwise the linkspeed sets \
refresh) +	portSel = read32(SKL_DPLL_CTRL1);
+	if ((portSel & (1 << (pllSel * 6 + 5))) && pllSel) { // DPLL0 might only know DP \
mode +		// enable pgm on our PLL in case that's currently disabled
+		write32(SKL_DPLL_CTRL1, portSel | (1 << (pllSel * 6)));
+
+		write32(SKL_DPLL1_CFGCR1 + (pllSel - 1) * 8,
+			1 << 31 |
+			wrpll_params.dco_fraction << 9 |
+			wrpll_params.dco_integer);
+		write32(SKL_DPLL1_CFGCR2 + (pllSel - 1) * 8,
+			 wrpll_params.qdiv_ratio << 8 |
+			 wrpll_params.qdiv_mode << 7 |
+			 wrpll_params.kdiv << 5 |
+			 wrpll_params.pdiv << 2 |
+			 wrpll_params.central_freq);
+		read32(SKL_DPLL1_CFGCR1 + (pllSel - 1) * 8);
+		read32(SKL_DPLL1_CFGCR2 + (pllSel - 1) * 8);
+
+		//assuming DPLL0 and 1 are already enabled by the BIOS if in use (LCPLL1,2 regs)
+
+		spin(5);
+		if (read32(SKL_DPLL_STATUS) & (1 << (pllSel * 8))) {
+			TRACE("Programmed PLL; PLL is locked\n");
+		} else {
+			TRACE("Programmed PLL; PLL did not lock\n");
+		}
+		TRACE("Skylake DPLL_CFGCR1 now: 0x%" B_PRIx32 "\n",
+			read32(SKL_DPLL1_CFGCR1 + (pllSel - 1) * 8));
+		TRACE("Skylake DPLL_CFGCR2 now: 0x%" B_PRIx32 "\n",
+			read32(SKL_DPLL1_CFGCR2 + (pllSel - 1) * 8));
+	} else {
+		TRACE("PLL programming not needed, skipping.\n");
+	}
+
 	TRACE("Skylake DPLL_CTRL1: 0x%" B_PRIx32 "\n", read32(SKL_DPLL_CTRL1));
 	TRACE("Skylake DPLL_CTRL2: 0x%" B_PRIx32 "\n", read32(SKL_DPLL_CTRL2));
 	TRACE("Skylake DPLL_STATUS: 0x%" B_PRIx32 "\n", read32(SKL_DPLL_STATUS));
diff --git a/src/add-ons/accelerants/intel_extreme/Pipes.h \
b/src/add-ons/accelerants/intel_extreme/Pipes.h index fcf160b08f..1c69805c4e 100644
--- a/src/add-ons/accelerants/intel_extreme/Pipes.h
+++ b/src/add-ons/accelerants/intel_extreme/Pipes.h
@@ -50,7 +50,7 @@ public:
 		void						ConfigureClocksSKL(
 										const skl_wrpll_params& wrpll_params,
 										uint32 pixelClock,
-										uint32 extraFlags);
+										port_index pllForPort);
 
 		// access to the various parts of the pipe
 		::FDILink*					FDI()
diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp \
b/src/add-ons/accelerants/intel_extreme/Ports.cpp index f09b8f5531..1124b019c1 100644
--- a/src/add-ons/accelerants/intel_extreme/Ports.cpp
+++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp
@@ -1527,16 +1527,6 @@ DigitalDisplayInterface::SetDisplayMode(display_mode* target, \
uint32 colorMode)  // Program general pipe config
 	fPipe->Configure(target);
 
-	//pll_divisors divisors;
-	//compute_pll_divisors(&target->timing, &divisors, false);
-
-	//uint32 extraPLLFlags = 0;
-	//if (gInfo->shared_info->device_type.Generation() >= 3)
-	//	extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK;
-
-	// Program pipe PLL's
-	//fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags);
-
 	if (gInfo->shared_info->device_type.Generation() <= 8) {
 		unsigned int r2_out, n2_out, p_out;
 		hsw_ddi_calculate_wrpll(
@@ -1546,9 +1536,11 @@ DigitalDisplayInterface::SetDisplayMode(display_mode* target, \
uint32 colorMode)  skl_wrpll_params wrpll_params;
 		skl_ddi_calculate_wrpll(
 			target->timing.pixel_clock * 1000 /* in Hz */,
-			gInfo->shared_info->pll_info.reference_frequency,//fixme Hz? kHz?
+			24000,//gInfo->shared_info->pll_info.reference_frequency, //fixme
 			&wrpll_params);
-		fPipe->ConfigureClocksSKL(wrpll_params, target->timing.pixel_clock, 0);
+		fPipe->ConfigureClocksSKL(wrpll_params,
+			target->timing.pixel_clock,
+			PortIndex());
 	}
 
 	// Program target display mode
diff --git a/src/add-ons/accelerants/intel_extreme/Ports.h \
b/src/add-ons/accelerants/intel_extreme/Ports.h index e69beaf6eb..de4ac1eb1d 100644
--- a/src/add-ons/accelerants/intel_extreme/Ports.h
+++ b/src/add-ons/accelerants/intel_extreme/Ports.h
@@ -32,15 +32,6 @@ enum port_type {
 	INTEL_PORT_TYPE_HDMI
 };
 
-enum port_index {
-	INTEL_PORT_ANY,				// wildcard for lookup functions
-	INTEL_PORT_A,
-	INTEL_PORT_B,
-	INTEL_PORT_C,
-	INTEL_PORT_D,
-	INTEL_PORT_E
-};
-
 
 class Port {
 public:
diff --git a/src/add-ons/accelerants/intel_extreme/pll.cpp \
b/src/add-ons/accelerants/intel_extreme/pll.cpp index ed765b6da7..a04e8e4d15 100644
--- a/src/add-ons/accelerants/intel_extreme/pll.cpp
+++ b/src/add-ons/accelerants/intel_extreme/pll.cpp
@@ -591,6 +591,15 @@ refclk_activate_ilk(bool hasPanel)
 #define VCO_MIN 2400
 #define VCO_MAX 4800
 
+static uint64 AbsSubtr64(uint64 nr1, uint64 nr2)
+{
+	if (nr1 >= nr2) {
+		return nr1 - nr2;
+	} else {
+		return nr2 - nr1;
+	}
+}
+
 struct hsw_wrpll_rnp {
 	unsigned p, n2, r2;
 };
@@ -700,8 +709,8 @@ static void hsw_wrpll_update_rnp(uint64 freq2k, unsigned int \
                budget,
 	 */
 	a = freq2k * budget * p * r2;
 	b = freq2k * budget * best->p * best->r2;
-	diff = labs((uint64)freq2k * p * r2 - LC_FREQ_2K * n2);
-	diff_best = labs((uint64)freq2k * best->p * best->r2 -
+	diff = AbsSubtr64((uint64)freq2k * p * r2, LC_FREQ_2K * n2);
+	diff_best = AbsSubtr64((uint64)freq2k * best->p * best->r2,
 			     LC_FREQ_2K * best->n2);
 	c = 1000000 * diff;
 	d = 1000000 * diff_best;
@@ -812,8 +821,8 @@ static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
 {
 	uint64 deviation;
 
-	deviation = ((uint64)10000 * labs(dco_freq - central_freq)
-			      / (uint64)central_freq);
+	deviation = ((uint64)10000 * AbsSubtr64(dco_freq, central_freq)
+			      / central_freq);
 
 	/* positive deviation */
 	if (dco_freq >= central_freq) {
@@ -823,6 +832,11 @@ static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
 			ctx->central_freq = central_freq;
 			ctx->dco_freq = dco_freq;
 			ctx->p = divider;
+
+			TRACE("%s: DCO central frequency %" B_PRIu64 "Hz\n", __func__, central_freq);
+			TRACE("%s: DCO frequency %" B_PRIu64 "Hz\n", __func__, dco_freq);
+			TRACE("%s: positive offset accepted, deviation %" B_PRIu64 "\n",
+				__func__, deviation);
 		}
 	/* negative deviation */
 	} else if (deviation < SKL_DCO_MAX_NDEVIATION &&
@@ -831,6 +845,11 @@ static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
 		ctx->central_freq = central_freq;
 		ctx->dco_freq = dco_freq;
 		ctx->p = divider;
+
+		TRACE("%s: DCO central frequency %" B_PRIu64 "Hz\n", __func__, central_freq);
+		TRACE("%s: DCO frequency %" B_PRIu64 "Hz\n", __func__, dco_freq);
+		TRACE("%s: negative offset accepted, deviation %" B_PRIu64 "\n",
+			__func__, deviation);
 	}
 }
 
@@ -946,6 +965,10 @@ static void skl_wrpll_params_populate(struct skl_wrpll_params \
*params,  params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
 
 	dco_freq = p0 * p1 * p2 * afe_clock;
+	TRACE("%s: AFE frequency %" B_PRIu64 "Hz\n", __func__, afe_clock);
+	TRACE("%s: p0: %" B_PRIu32 ", p1: %" B_PRIu32 ", p2: %" B_PRIu32 "\n",
+		__func__, p0,p1,p2);
+	TRACE("%s: DCO frequency %" B_PRIu64 "Hz\n", __func__, dco_freq);
 
 	/*
 	 * Intermediate values are in Hz.
@@ -954,8 +977,11 @@ static void skl_wrpll_params_populate(struct skl_wrpll_params \
*params,  params->dco_integer = (uint64)dco_freq / ((uint64)ref_clock * 1000);
 	params->dco_fraction = (
 			(uint64)dco_freq / ((uint64)ref_clock / 1000) -
-			(uint64)params->dco_integer * 1000000 * 0x8000) /
+			(uint64)params->dco_integer * 1000000) * 0x8000 /
 			1000000;
+
+	TRACE("%s: DCO integer %" B_PRIu32 "\n", __func__, params->dco_integer);
+	TRACE("%s: DCO fraction 0x%" B_PRIx32 "\n", __func__, params->dco_fraction);
 }
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@@ -1021,6 +1047,7 @@ skip_remaining_dividers:
 		TRACE("%s: No valid divider found for %dHz\n", __func__, clock);
 		return false;
 	}
+	TRACE("%s: Full devider (p) found is %d\n", __func__, ctx.p);
 
 	/*
 	 * gcc incorrectly analyses that these can be used without being


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic