intel_extreme: Sandy/IvyBridge fix 4 lanes DP detect, fully pgm eDP link

This commit is contained in:
Rudolf Cornelissen
2022-02-04 19:56:27 +01:00
parent a18ff64517
commit 4b5e0c3bcd
5 changed files with 70 additions and 18 deletions
@@ -861,7 +861,11 @@ struct intel_free_graphics_memory {
#define INTEL_DISP_PORT_WIDTH_MASK (7 << INTEL_DISP_PORT_WIDTH_SHIFT) #define INTEL_DISP_PORT_WIDTH_MASK (7 << INTEL_DISP_PORT_WIDTH_SHIFT)
#define INTEL_DISP_PORT_WIDTH_1 0 #define INTEL_DISP_PORT_WIDTH_1 0
#define INTEL_DISP_PORT_WIDTH_2 1 #define INTEL_DISP_PORT_WIDTH_2 1
#define INTEL_DISP_PORT_WIDTH_4 2 #define INTEL_DISP_PORT_WIDTH_4 3
#define INTEL_DISP_EDP_PLL_FREQ_SHIFT 16
#define INTEL_DISP_EDP_PLL_FREQ_MASK (3 << INTEL_DISP_EDP_PLL_FREQ_SHIFT)
#define INTEL_DISP_EDP_PLL_FREQ_270 0
#define INTEL_DISP_EDP_PLL_FREQ_162 1
#define INTEL_TRANSCODER_A_DP_CTL (0x0300 | REGS_SOUTH_TRANSCODER_PORT) #define INTEL_TRANSCODER_A_DP_CTL (0x0300 | REGS_SOUTH_TRANSCODER_PORT)
#define INTEL_TRANSCODER_B_DP_CTL (0x1300 | REGS_SOUTH_TRANSCODER_PORT) #define INTEL_TRANSCODER_B_DP_CTL (0x1300 | REGS_SOUTH_TRANSCODER_PORT)
@@ -281,7 +281,6 @@ FDILink::PreTrain(display_timing* target, uint32* linkBandwidth, uint32* lanes,
TRACE("%s: FDI Link Colordepth: %" B_PRIu32 "\n", __func__, *bitsPerPixel); TRACE("%s: FDI Link Colordepth: %" B_PRIu32 "\n", __func__, *bitsPerPixel);
// Khz / 10. ( each output octet encoded as 10 bits. // Khz / 10. ( each output octet encoded as 10 bits.
// note: if used for eDP (PORT_A) might be we should check reg. DP_CTL (0x64000), bit 16-17 (Ivy).
*linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10; *linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10;
//Reserving 5% bandwidth for possible spread spectrum clock use //Reserving 5% bandwidth for possible spread spectrum clock use
uint32 bps = target->pixel_clock * *bitsPerPixel * 21 / 20; uint32 bps = target->pixel_clock * *bitsPerPixel * 21 / 20;
@@ -331,7 +331,7 @@ Pipe::ConfigureScalePos(display_mode* target)
void void
Pipe::ConfigureTimings(display_mode* target, bool hardware) Pipe::ConfigureTimings(display_mode* target, bool hardware, port_index portIndex)
{ {
CALLED(); CALLED();
@@ -373,6 +373,13 @@ Pipe::ConfigureTimings(display_mode* target, bool hardware)
ConfigureScalePos(target); ConfigureScalePos(target);
// transcoder is not applicable if eDP is targeted on Sandy- and IvyBridge
if ((gInfo->shared_info->device_type.InGroup(INTEL_GROUP_SNB) ||
gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IVB)) &&
(portIndex == INTEL_PORT_A)) {
return;
}
if (fHasTranscoder && hardware) { if (fHasTranscoder && hardware) {
_ConfigureTranscoder(target); _ConfigureTranscoder(target);
} }
@@ -47,7 +47,8 @@ public:
uint32 bitsPerPixel); uint32 bitsPerPixel);
void ConfigureScalePos(display_mode* mode); void ConfigureScalePos(display_mode* mode);
void ConfigureTimings(display_mode* mode, void ConfigureTimings(display_mode* mode,
bool hardware = true); bool hardware = true,
port_index portIndex = INTEL_PORT_ANY);
void ConfigureClocks( void ConfigureClocks(
const pll_divisors& divisors, const pll_divisors& divisors,
uint32 pixelClock, uint32 pixelClock,
@@ -1152,7 +1152,6 @@ status_t
DisplayPort::_SetPortLinkGen4(const display_timing& timing) DisplayPort::_SetPortLinkGen4(const display_timing& timing)
{ {
// Khz / 10. ( each output octet encoded as 10 bits. // 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?
uint32 linkBandwidth = 270000; //khz uint32 linkBandwidth = 270000; //khz
uint32 fPipeOffset = 0; uint32 fPipeOffset = 0;
@@ -1216,8 +1215,7 @@ status_t
DisplayPort::_SetPortLinkGen6(const display_timing& timing) DisplayPort::_SetPortLinkGen6(const display_timing& timing)
{ {
// Khz / 10. ( each output octet encoded as 10 bits. // Khz / 10. ( each output octet encoded as 10 bits.
//uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10; //=270000 khz //note: (fixme) eDP is fixed option 162 or 270Mc, other DPs go via DPLL programming to one of the same vals.
//fixme: eDP is fixed option 162 or 270Mc, other DPs go via DPLL programming to one of the same vals.
uint32 linkBandwidth = 270000; //khz uint32 linkBandwidth = 270000; //khz
TRACE("%s: DP link reference clock is %gMhz\n", __func__, linkBandwidth / 1000.0f); TRACE("%s: DP link reference clock is %gMhz\n", __func__, linkBandwidth / 1000.0f);
@@ -1259,8 +1257,7 @@ DisplayPort::_SetPortLinkGen6(const display_timing& timing)
} }
TRACE("%s: DP link colordepth: %" B_PRIu32 "\n", __func__, bitsPerPixel); TRACE("%s: DP link colordepth: %" B_PRIu32 "\n", __func__, bitsPerPixel);
uint32 lanes = uint32 lanes = ((read32(_PortRegister()) & INTEL_DISP_PORT_WIDTH_MASK) >> INTEL_DISP_PORT_WIDTH_SHIFT) + 1;
1 << ((read32(_PortRegister()) & INTEL_DISP_PORT_WIDTH_MASK) >> INTEL_DISP_PORT_WIDTH_SHIFT);
if (lanes > 4) { if (lanes > 4) {
ERROR("%s: DP illegal number of lanes set.\n", __func__); ERROR("%s: DP illegal number of lanes set.\n", __func__);
return B_ERROR; return B_ERROR;
@@ -1386,16 +1383,60 @@ DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
PanelFitter* fitter = fPipe->PFT(); PanelFitter* fitter = fPipe->PFT();
if (fitter != NULL) if (fitter != NULL)
fitter->Enable(hardwareTarget); fitter->Enable(hardwareTarget);
// we should skip FDI if PORT_A, but need pipe M/N programming (is eDP link), so call always for now
FDILink* link = fPipe->FDI();
if (link != NULL) {
uint32 lanes = 0; uint32 lanes = 0;
uint32 linkBandwidth = 0; uint32 linkBandwidth = 0;
uint32 bitsPerPixel = 0; uint32 bitsPerPixel = 0;
if (PortIndex() != INTEL_PORT_A) {
FDILink* link = fPipe->FDI();
if (link != NULL) {
link->PreTrain(&hardwareTarget, &linkBandwidth, &lanes, &bitsPerPixel); link->PreTrain(&hardwareTarget, &linkBandwidth, &lanes, &bitsPerPixel);
fPipe->SetFDILink(hardwareTarget, linkBandwidth, lanes, bitsPerPixel); fPipe->SetFDILink(hardwareTarget, linkBandwidth, lanes, bitsPerPixel);
link->Train(&hardwareTarget, lanes); link->Train(&hardwareTarget, lanes);
} }
} else {
// 'local' eDP port is in use
linkBandwidth =
(read32(INTEL_DISPLAY_PORT_A) & INTEL_DISP_EDP_PLL_FREQ_MASK) >> INTEL_DISP_EDP_PLL_FREQ_SHIFT;
switch (linkBandwidth) {
case INTEL_DISP_EDP_PLL_FREQ_270:
linkBandwidth = 270000; //khz
break;
case INTEL_DISP_EDP_PLL_FREQ_162:
linkBandwidth = 162000; //khz
break;
default:
TRACE("%s: eDP illegal reference clock ID set, assuming 270Mhz.\n", __func__);
linkBandwidth = 270000; //khz
}
bitsPerPixel =
(read32(INTEL_DISPLAY_A_PIPE_CONTROL) & INTEL_PIPE_BPC_MASK) >> INTEL_PIPE_COLOR_SHIFT;
switch (bitsPerPixel) {
case INTEL_PIPE_8BPC:
bitsPerPixel = 24;
break;
case INTEL_PIPE_10BPC:
bitsPerPixel = 30;
break;
case INTEL_PIPE_6BPC:
bitsPerPixel = 18;
break;
case INTEL_PIPE_12BPC:
bitsPerPixel = 36;
break;
default:
bitsPerPixel = 0;
}
lanes = 2; //fixme: doc is incorrect on SandyBridge (DP_CTL b19..21 is NOT port_width)
if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_IVB)) {
lanes =
((read32(_PortRegister()) & INTEL_DISP_PORT_WIDTH_MASK) >> INTEL_DISP_PORT_WIDTH_SHIFT) + 1;
}
fPipe->SetFDILink(hardwareTarget, linkBandwidth, lanes, bitsPerPixel);
}
// Program general pipe config // Program general pipe config
fPipe->Configure(target); fPipe->Configure(target);
@@ -1403,7 +1444,7 @@ DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
// Pll programming is not needed for (e)DP.. // Pll programming is not needed for (e)DP..
// Program target display mode // Program target display mode
fPipe->ConfigureTimings(target, !needsScaling); fPipe->ConfigureTimings(target, !needsScaling, PortIndex());
} else { } else {
TRACE("%s: Setting display mode via fallback: using scaling!\n", __func__); TRACE("%s: Setting display mode via fallback: using scaling!\n", __func__);
// Keep monitor at native mode and scale image to that // Keep monitor at native mode and scale image to that