intel_extreme:DP links on sky- upto/incl coffeelake are now done (refclk detection added)

This commit is contained in:
Rudolf Cornelissen 2021-12-07 00:42:42 +00:00
parent 6c88202d33
commit 9ef22aa9d7
5 changed files with 73 additions and 27 deletions

View File

@ -612,9 +612,21 @@ struct intel_free_graphics_memory {
#define SKL_DPLL2_CFGCR2 (0xc04c | REGS_NORTH_PIPE_AND_PORT)
#define SKL_DPLL3_CFGCR1 (0xc050 | REGS_NORTH_PIPE_AND_PORT)
#define SKL_DPLL3_CFGCR2 (0xc054 | REGS_NORTH_PIPE_AND_PORT)
// These exist also still in CoffeeLake (confirmed):
#define SKL_DPLL_CTRL1 (0xc058 | REGS_NORTH_PIPE_AND_PORT)
#define SKL_DPLL_CTRL2 (0xc05c | REGS_NORTH_PIPE_AND_PORT)
#define SKL_DPLL_STATUS (0xc060 | REGS_NORTH_PIPE_AND_PORT)
#define SKL_DPLL0_DP_LINKRATE_SHIFT 1
#define SKL_DPLL1_DP_LINKRATE_SHIFT 7
#define SKL_DPLL2_DP_LINKRATE_SHIFT 13
#define SKL_DPLL3_DP_LINKRATE_SHIFT 19
#define SKL_DPLL_DP_LINKRATE_MASK 7
#define SKL_DPLL_CTRL1_2700 0
#define SKL_DPLL_CTRL1_1350 1
#define SKL_DPLL_CTRL1_810 2
#define SKL_DPLL_CTRL1_1620 3
#define SKL_DPLL_CTRL1_1080 4
#define SKL_DPLL_CTRL1_2160 5
// Icelake PLLs
#define ICL_DSSM 0x51004

View File

@ -463,71 +463,71 @@ Pipe::ConfigureClocks(const pll_divisors& divisors, uint32 pixelClock,
void
Pipe::ConfigureClocksSKL(const skl_wrpll_params& wrpll_params, uint32 pixelClock,
port_index pllForPort)
port_index pllForPort, uint32* pllSel)
{
CALLED();
//find our PLL as set by the BIOS
uint32 portSel = read32(SKL_DPLL_CTRL2);
uint32 pllSel = 0;
*pllSel = 0xff;
switch (pllForPort) {
case INTEL_PORT_A:
pllSel = (portSel & 0x0006) >> 1;
*pllSel = (portSel & 0x0006) >> 1;
break;
case INTEL_PORT_B:
pllSel = (portSel & 0x0030) >> 4;
*pllSel = (portSel & 0x0030) >> 4;
break;
case INTEL_PORT_C:
pllSel = (portSel & 0x0180) >> 7;
*pllSel = (portSel & 0x0180) >> 7;
break;
case INTEL_PORT_D:
pllSel = (portSel & 0x0c00) >> 10;
*pllSel = (portSel & 0x0c00) >> 10;
break;
case INTEL_PORT_E:
pllSel = (portSel & 0x6000) >> 13;
*pllSel = (portSel & 0x6000) >> 13;
break;
default:
TRACE("No port selected!");
return;
}
TRACE("PLL selected is %" B_PRIx32 "\n", pllSel);
TRACE("PLL selected is %" B_PRIx32 "\n", *pllSel);
TRACE("Skylake DPLL_CFGCR1 0x%" B_PRIx32 "\n",
read32(SKL_DPLL1_CFGCR1 + (pllSel - 1) * 8));
read32(SKL_DPLL1_CFGCR1 + (*pllSel - 1) * 8));
TRACE("Skylake DPLL_CFGCR2 0x%" B_PRIx32 "\n",
read32(SKL_DPLL1_CFGCR2 + (pllSel - 1) * 8));
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
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_DPLL_CTRL1, portSel | (1 << (*pllSel * 6)));
write32(SKL_DPLL1_CFGCR1 + (pllSel - 1) * 8,
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,
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);
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))) {
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));
read32(SKL_DPLL1_CFGCR1 + (*pllSel - 1) * 8));
TRACE("Skylake DPLL_CFGCR2 now: 0x%" B_PRIx32 "\n",
read32(SKL_DPLL1_CFGCR2 + (pllSel - 1) * 8));
read32(SKL_DPLL1_CFGCR2 + (*pllSel - 1) * 8));
} else {
TRACE("PLL programming not needed, skipping.\n");
}

View File

@ -50,7 +50,8 @@ public:
void ConfigureClocksSKL(
const skl_wrpll_params& wrpll_params,
uint32 pixelClock,
port_index pllForPort);
port_index pllForPort,
uint32* pllSel);
// access to the various parts of the pipe
::FDILink* FDI()

View File

@ -1449,13 +1449,43 @@ DigitalDisplayInterface::IsConnected()
}
status_t
DigitalDisplayInterface::_SetPortLinkGen8(const display_timing& timing)
DigitalDisplayInterface::_SetPortLinkGen8(const display_timing& timing, uint32 pllSel)
{
// Khz / 10. ( each output octet encoded as 10 bits.
//uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10; //=270000 khz
//fixme: always so?
//fixme: always so on pre gen 9?
uint32 linkBandwidth = 270000; //khz
if (gInfo->shared_info->device_type.Generation() >= 9) {
if (pllSel != 0xff) {
linkBandwidth = (read32(SKL_DPLL_CTRL1) >> (1 + 6 * pllSel)) & SKL_DPLL_DP_LINKRATE_MASK;
switch (linkBandwidth) {
case SKL_DPLL_CTRL1_2700:
linkBandwidth = 2700000 / 5;
break;
case SKL_DPLL_CTRL1_1350:
linkBandwidth = 1350000 / 5;
break;
case SKL_DPLL_CTRL1_810:
linkBandwidth = 810000 / 5;
break;
case SKL_DPLL_CTRL1_1620:
linkBandwidth = 1620000 / 5;
break;
case SKL_DPLL_CTRL1_1080:
linkBandwidth = 1080000 / 5;
break;
case SKL_DPLL_CTRL1_2160:
linkBandwidth = 2160000 / 5;
break;
default:
ERROR("%s: DDI No known DP-link reference clock selected, assuming default\n", __func__);
break;
}
} else {
ERROR("%s: DDI No known PLL selected, assuming default DP-link reference\n", __func__);
}
}
TRACE("%s: DDI DP-link reference clock is %gMhz\n", __func__, linkBandwidth / 1000.0f);
uint32 fPipeOffset = 0;
switch (fPipe->Index()) {
case INTEL_PIPE_B:
@ -1609,6 +1639,7 @@ DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode)
// Program general pipe config
fPipe->Configure(target);
uint32 pllSel = 0xff; // no PLL selected
if (gInfo->shared_info->device_type.Generation() <= 8) {
unsigned int r2_out, n2_out, p_out;
hsw_ddi_calculate_wrpll(
@ -1622,12 +1653,13 @@ DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode)
&wrpll_params);
fPipe->ConfigureClocksSKL(wrpll_params,
hardwareTarget.pixel_clock,
PortIndex());
PortIndex(),
&pllSel);
}
// Program target display mode
fPipe->ConfigureTimings(target, !needsScaling);
_SetPortLinkGen8(hardwareTarget);
_SetPortLinkGen8(hardwareTarget, pllSel);
// Set fCurrentMode to our set display mode
memcpy(&fCurrentMode, target, sizeof(display_mode));

View File

@ -218,7 +218,8 @@ virtual addr_t _PortRegister();
private:
uint8 fMaxLanes;
status_t _SetPortLinkGen8(const display_timing& timing);
status_t _SetPortLinkGen8(const display_timing& timing,
uint32 pllSel);
};