intel_extreme:DP links on sky- upto/incl coffeelake are now done (refclk detection added)
This commit is contained in:
@@ -612,9 +612,21 @@ struct intel_free_graphics_memory {
|
|||||||
#define SKL_DPLL2_CFGCR2 (0xc04c | REGS_NORTH_PIPE_AND_PORT)
|
#define SKL_DPLL2_CFGCR2 (0xc04c | REGS_NORTH_PIPE_AND_PORT)
|
||||||
#define SKL_DPLL3_CFGCR1 (0xc050 | 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)
|
#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_CTRL1 (0xc058 | REGS_NORTH_PIPE_AND_PORT)
|
||||||
#define SKL_DPLL_CTRL2 (0xc05c | 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_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
|
// Icelake PLLs
|
||||||
#define ICL_DSSM 0x51004
|
#define ICL_DSSM 0x51004
|
||||||
|
|||||||
@@ -463,71 +463,71 @@ Pipe::ConfigureClocks(const pll_divisors& divisors, uint32 pixelClock,
|
|||||||
|
|
||||||
void
|
void
|
||||||
Pipe::ConfigureClocksSKL(const skl_wrpll_params& wrpll_params, uint32 pixelClock,
|
Pipe::ConfigureClocksSKL(const skl_wrpll_params& wrpll_params, uint32 pixelClock,
|
||||||
port_index pllForPort)
|
port_index pllForPort, uint32* pllSel)
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
//find our PLL as set by the BIOS
|
//find our PLL as set by the BIOS
|
||||||
uint32 portSel = read32(SKL_DPLL_CTRL2);
|
uint32 portSel = read32(SKL_DPLL_CTRL2);
|
||||||
uint32 pllSel = 0;
|
*pllSel = 0xff;
|
||||||
switch (pllForPort) {
|
switch (pllForPort) {
|
||||||
case INTEL_PORT_A:
|
case INTEL_PORT_A:
|
||||||
pllSel = (portSel & 0x0006) >> 1;
|
*pllSel = (portSel & 0x0006) >> 1;
|
||||||
break;
|
break;
|
||||||
case INTEL_PORT_B:
|
case INTEL_PORT_B:
|
||||||
pllSel = (portSel & 0x0030) >> 4;
|
*pllSel = (portSel & 0x0030) >> 4;
|
||||||
break;
|
break;
|
||||||
case INTEL_PORT_C:
|
case INTEL_PORT_C:
|
||||||
pllSel = (portSel & 0x0180) >> 7;
|
*pllSel = (portSel & 0x0180) >> 7;
|
||||||
break;
|
break;
|
||||||
case INTEL_PORT_D:
|
case INTEL_PORT_D:
|
||||||
pllSel = (portSel & 0x0c00) >> 10;
|
*pllSel = (portSel & 0x0c00) >> 10;
|
||||||
break;
|
break;
|
||||||
case INTEL_PORT_E:
|
case INTEL_PORT_E:
|
||||||
pllSel = (portSel & 0x6000) >> 13;
|
*pllSel = (portSel & 0x6000) >> 13;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
TRACE("No port selected!");
|
TRACE("No port selected!");
|
||||||
return;
|
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",
|
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",
|
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)
|
// only program PLL's that are in non-DP mode (otherwise the linkspeed sets refresh)
|
||||||
portSel = read32(SKL_DPLL_CTRL1);
|
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
|
// 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 |
|
1 << 31 |
|
||||||
wrpll_params.dco_fraction << 9 |
|
wrpll_params.dco_fraction << 9 |
|
||||||
wrpll_params.dco_integer);
|
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_ratio << 8 |
|
||||||
wrpll_params.qdiv_mode << 7 |
|
wrpll_params.qdiv_mode << 7 |
|
||||||
wrpll_params.kdiv << 5 |
|
wrpll_params.kdiv << 5 |
|
||||||
wrpll_params.pdiv << 2 |
|
wrpll_params.pdiv << 2 |
|
||||||
wrpll_params.central_freq);
|
wrpll_params.central_freq);
|
||||||
read32(SKL_DPLL1_CFGCR1 + (pllSel - 1) * 8);
|
read32(SKL_DPLL1_CFGCR1 + (*pllSel - 1) * 8);
|
||||||
read32(SKL_DPLL1_CFGCR2 + (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)
|
//assuming DPLL0 and 1 are already enabled by the BIOS if in use (LCPLL1,2 regs)
|
||||||
|
|
||||||
spin(5);
|
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");
|
TRACE("Programmed PLL; PLL is locked\n");
|
||||||
} else {
|
} else {
|
||||||
TRACE("Programmed PLL; PLL did not lock\n");
|
TRACE("Programmed PLL; PLL did not lock\n");
|
||||||
}
|
}
|
||||||
TRACE("Skylake DPLL_CFGCR1 now: 0x%" B_PRIx32 "\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",
|
TRACE("Skylake DPLL_CFGCR2 now: 0x%" B_PRIx32 "\n",
|
||||||
read32(SKL_DPLL1_CFGCR2 + (pllSel - 1) * 8));
|
read32(SKL_DPLL1_CFGCR2 + (*pllSel - 1) * 8));
|
||||||
} else {
|
} else {
|
||||||
TRACE("PLL programming not needed, skipping.\n");
|
TRACE("PLL programming not needed, skipping.\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ public:
|
|||||||
void ConfigureClocksSKL(
|
void ConfigureClocksSKL(
|
||||||
const skl_wrpll_params& wrpll_params,
|
const skl_wrpll_params& wrpll_params,
|
||||||
uint32 pixelClock,
|
uint32 pixelClock,
|
||||||
port_index pllForPort);
|
port_index pllForPort,
|
||||||
|
uint32* pllSel);
|
||||||
|
|
||||||
// access to the various parts of the pipe
|
// access to the various parts of the pipe
|
||||||
::FDILink* FDI()
|
::FDILink* FDI()
|
||||||
|
|||||||
@@ -1449,13 +1449,43 @@ DigitalDisplayInterface::IsConnected()
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_t
|
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.
|
//fixme: always so on pre gen 9?
|
||||||
//uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10; //=270000 khz
|
|
||||||
//fixme: always so?
|
|
||||||
uint32 linkBandwidth = 270000; //khz
|
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;
|
uint32 fPipeOffset = 0;
|
||||||
switch (fPipe->Index()) {
|
switch (fPipe->Index()) {
|
||||||
case INTEL_PIPE_B:
|
case INTEL_PIPE_B:
|
||||||
@@ -1609,6 +1639,7 @@ DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode)
|
|||||||
// Program general pipe config
|
// Program general pipe config
|
||||||
fPipe->Configure(target);
|
fPipe->Configure(target);
|
||||||
|
|
||||||
|
uint32 pllSel = 0xff; // no PLL selected
|
||||||
if (gInfo->shared_info->device_type.Generation() <= 8) {
|
if (gInfo->shared_info->device_type.Generation() <= 8) {
|
||||||
unsigned int r2_out, n2_out, p_out;
|
unsigned int r2_out, n2_out, p_out;
|
||||||
hsw_ddi_calculate_wrpll(
|
hsw_ddi_calculate_wrpll(
|
||||||
@@ -1622,12 +1653,13 @@ DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode)
|
|||||||
&wrpll_params);
|
&wrpll_params);
|
||||||
fPipe->ConfigureClocksSKL(wrpll_params,
|
fPipe->ConfigureClocksSKL(wrpll_params,
|
||||||
hardwareTarget.pixel_clock,
|
hardwareTarget.pixel_clock,
|
||||||
PortIndex());
|
PortIndex(),
|
||||||
|
&pllSel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Program target display mode
|
// Program target display mode
|
||||||
fPipe->ConfigureTimings(target, !needsScaling);
|
fPipe->ConfigureTimings(target, !needsScaling);
|
||||||
_SetPortLinkGen8(hardwareTarget);
|
_SetPortLinkGen8(hardwareTarget, pllSel);
|
||||||
|
|
||||||
// Set fCurrentMode to our set display mode
|
// Set fCurrentMode to our set display mode
|
||||||
memcpy(&fCurrentMode, target, sizeof(display_mode));
|
memcpy(&fCurrentMode, target, sizeof(display_mode));
|
||||||
|
|||||||
@@ -218,7 +218,8 @@ virtual addr_t _PortRegister();
|
|||||||
private:
|
private:
|
||||||
uint8 fMaxLanes;
|
uint8 fMaxLanes;
|
||||||
|
|
||||||
status_t _SetPortLinkGen8(const display_timing& timing);
|
status_t _SetPortLinkGen8(const display_timing& timing,
|
||||||
|
uint32 pllSel);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user