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

View File

@ -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_1 0
#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_B_DP_CTL (0x1300 | REGS_SOUTH_TRANSCODER_PORT)

View File

@ -281,7 +281,6 @@ FDILink::PreTrain(display_timing* target, uint32* linkBandwidth, uint32* lanes,
TRACE("%s: FDI Link Colordepth: %" B_PRIu32 "\n", __func__, *bitsPerPixel);
// 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;
//Reserving 5% bandwidth for possible spread spectrum clock use
uint32 bps = target->pixel_clock * *bitsPerPixel * 21 / 20;

View File

@ -331,7 +331,7 @@ Pipe::ConfigureScalePos(display_mode* target)
void
Pipe::ConfigureTimings(display_mode* target, bool hardware)
Pipe::ConfigureTimings(display_mode* target, bool hardware, port_index portIndex)
{
CALLED();
@ -373,6 +373,13 @@ Pipe::ConfigureTimings(display_mode* target, bool hardware)
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) {
_ConfigureTranscoder(target);
}

View File

@ -47,7 +47,8 @@ public:
uint32 bitsPerPixel);
void ConfigureScalePos(display_mode* mode);
void ConfigureTimings(display_mode* mode,
bool hardware = true);
bool hardware = true,
port_index portIndex = INTEL_PORT_ANY);
void ConfigureClocks(
const pll_divisors& divisors,
uint32 pixelClock,

View File

@ -1152,7 +1152,6 @@ status_t
DisplayPort::_SetPortLinkGen4(const display_timing& timing)
{
// Khz / 10. ( each output octet encoded as 10 bits.
//uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10; //=270000 khz
//fixme: always so?
uint32 linkBandwidth = 270000; //khz
uint32 fPipeOffset = 0;
@ -1216,8 +1215,7 @@ status_t
DisplayPort::_SetPortLinkGen6(const display_timing& timing)
{
// Khz / 10. ( each output octet encoded as 10 bits.
//uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10; //=270000 khz
//fixme: eDP is fixed option 162 or 270Mc, other DPs go via DPLL programming to one of the same vals.
//note: (fixme) eDP is fixed option 162 or 270Mc, other DPs go via DPLL programming to one of the same vals.
uint32 linkBandwidth = 270000; //khz
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);
uint32 lanes =
1 << ((read32(_PortRegister()) & INTEL_DISP_PORT_WIDTH_MASK) >> INTEL_DISP_PORT_WIDTH_SHIFT);
uint32 lanes = ((read32(_PortRegister()) & INTEL_DISP_PORT_WIDTH_MASK) >> INTEL_DISP_PORT_WIDTH_SHIFT) + 1;
if (lanes > 4) {
ERROR("%s: DP illegal number of lanes set.\n", __func__);
return B_ERROR;
@ -1386,15 +1383,59 @@ DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
PanelFitter* fitter = fPipe->PFT();
if (fitter != NULL)
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 linkBandwidth = 0;
uint32 bitsPerPixel = 0;
link->PreTrain(&hardwareTarget, &linkBandwidth, &lanes, &bitsPerPixel);
uint32 lanes = 0;
uint32 linkBandwidth = 0;
uint32 bitsPerPixel = 0;
if (PortIndex() != INTEL_PORT_A) {
FDILink* link = fPipe->FDI();
if (link != NULL) {
link->PreTrain(&hardwareTarget, &linkBandwidth, &lanes, &bitsPerPixel);
fPipe->SetFDILink(hardwareTarget, linkBandwidth, lanes, bitsPerPixel);
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);
link->Train(&hardwareTarget, lanes);
}
// Program general pipe config
@ -1403,7 +1444,7 @@ DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
// Pll programming is not needed for (e)DP..
// Program target display mode
fPipe->ConfigureTimings(target, !needsScaling);
fPipe->ConfigureTimings(target, !needsScaling, PortIndex());
} else {
TRACE("%s: Setting display mode via fallback: using scaling!\n", __func__);
// Keep monitor at native mode and scale image to that