intel_extreme: added more pipeC support, fixes for eDP on DDI systems

This commit is contained in:
Rudolf Cornelissen
2022-02-27 22:25:04 +01:00
parent 11dc1393cf
commit 456e6f33dd
6 changed files with 94 additions and 41 deletions
@@ -1087,8 +1087,14 @@ struct intel_free_graphics_memory {
#define INTEL_GEN9_CLKGATE_DIS_4 (0x653c | REGS_NORTH_SHARED) #define INTEL_GEN9_CLKGATE_DIS_4 (0x653c | REGS_NORTH_SHARED)
#define BXT_GMBUSUNIT_CLK_GATE_DIS (1 << 14) #define BXT_GMBUSUNIT_CLK_GATE_DIS (1 << 14)
// gpu power wells // gpu power wells (confirmed skylake)
#define INTEL_PWR_WELL_CTL_2 (0x5404 | REGS_NORTH_SHARED) #define INTEL_PWR_WELL_CTL_1_BIOS (0x5400 | REGS_NORTH_SHARED)
#define INTEL_PWR_WELL_CTL_2_DRIVER (0x5404 | REGS_NORTH_SHARED)
// gpu pll enable registers (confirmed skylake)
#define INTEL_WRPLL_CTL_1_DPLL2 (0x6040 | REGS_NORTH_SHARED)
#define INTEL_WRPLL_CTL_2_DPLL3 (0x6060 | REGS_NORTH_SHARED)
#define WRPLL_PLL_ENABLE (1 << 31)
// TODO: on IronLake this is in the north shared block at 0x41000 // TODO: on IronLake this is in the north shared block at 0x41000
#define INTEL_VGA_DISPLAY_CONTROL (0x1400 | REGS_NORTH_PLANE_CONTROL) #define INTEL_VGA_DISPLAY_CONTROL (0x1400 | REGS_NORTH_PLANE_CONTROL)
@@ -57,7 +57,9 @@ PanelFitter::PanelFitter(pipe_index pipeIndex)
TRACE("%s: this fitter is enabled by the BIOS\n", __func__); TRACE("%s: this fitter is enabled by the BIOS\n", __func__);
} }
} else { } else {
TRACE("%s: this fitter is not setup by the BIOS\n", __func__); TRACE("%s: this fitter is not setup by the BIOS: Enabling.\n", __func__);
fitCtl |= PANEL_FITTER_ENABLED;
write32(fRegisterBase + PCH_PANEL_FITTER_CONTROL, fitCtl);
} }
} }
@@ -68,21 +68,21 @@ Pipe::Pipe(pipe_index pipeIndex)
fPipeOffset(0), fPipeOffset(0),
fPlaneOffset(0) fPlaneOffset(0)
{ {
if (pipeIndex == INTEL_PIPE_B) {
fPlaneOffset = INTEL_PLANE_OFFSET;
}
switch (pipeIndex) { switch (pipeIndex) {
case INTEL_PIPE_B: case INTEL_PIPE_B:
TRACE("Pipe B.\n"); TRACE("Pipe B.\n");
fPipeOffset = 0x1000; fPipeOffset = 0x1000;
fPlaneOffset = INTEL_PLANE_OFFSET;
break; break;
case INTEL_PIPE_C: case INTEL_PIPE_C:
TRACE("Pipe C.\n"); TRACE("Pipe C.\n");
fPipeOffset = 0x2000; fPipeOffset = 0x2000;
fPlaneOffset = INTEL_PLANE_OFFSET * 2;
break; break;
case INTEL_PIPE_D: case INTEL_PIPE_D:
TRACE("Pipe D.\n"); TRACE("Pipe D.\n");
fPipeOffset = 0xf000; fPipeOffset = 0xf000;
//no fPlaneOffset..
break; break;
default: default:
TRACE("Pipe A.\n"); TRACE("Pipe A.\n");
@@ -94,8 +94,7 @@ Pipe::Pipe(pipe_index pipeIndex)
// SkyLake: FDI gone. No more northbridge video. // SkyLake: FDI gone. No more northbridge video.
if ((gInfo->shared_info->pch_info != INTEL_PCH_NONE) && if ((gInfo->shared_info->pch_info != INTEL_PCH_NONE) &&
(gInfo->shared_info->device_type.Generation() <= 8)) { (gInfo->shared_info->device_type.Generation() <= 8)) {
TRACE("%s: Pipe %s routed through FDI\n", __func__, TRACE("%s: Pipe is routed through FDI\n", __func__);
(pipeIndex == INTEL_PIPE_A) ? "A" : "B");
// Program FDILink if PCH // Program FDILink if PCH
fFDILink = new(std::nothrow) FDILink(pipeIndex); fFDILink = new(std::nothrow) FDILink(pipeIndex);
@@ -561,7 +560,7 @@ Pipe::ConfigureClocksSKL(const skl_wrpll_params& wrpll_params, uint32 pixelClock
*pllSel = (portSel & 0x6000) >> 13; *pllSel = (portSel & 0x6000) >> 13;
break; break;
default: default:
TRACE("No port selected!"); TRACE("No port selected!\n");
return; return;
} }
TRACE("PLL selected is %" B_PRIx32 "\n", *pllSel); TRACE("PLL selected is %" B_PRIx32 "\n", *pllSel);
@@ -19,7 +19,7 @@
#include "PanelFitter.h" #include "PanelFitter.h"
#define MAX_PIPES 2 #define MAX_PIPES 4 // not all cards have this much though
void program_pipe_color_modes(uint32 colorMode); void program_pipe_color_modes(uint32 colorMode);
+69 -30
View File
@@ -1721,41 +1721,24 @@ DigitalDisplayInterface::IsConnected()
PortName(), fMaxLanes); PortName(), fMaxLanes);
// fetch EDID but determine 'in use' later (below) so we also catch screens that fail EDID // fetch EDID but determine 'in use' later (below) so we also catch screens that fail EDID
HasEDID(); bool edidDetected = HasEDID();
// scan all our pipes to find the one connected to the current port and check it's enabled // On laptops we always have an internal panel.. (on the eDP port on DDI systems, fixed on eDP pipe)
uint32 pipeState = 0; uint32 pipeState = 0;
for (uint32 pipeCnt = 0; pipeCnt < 4; pipeCnt++) {
switch (pipeCnt) {
case 0:
pipeState = read32(PIPE_DDI_FUNC_CTL_A);
break;
case 1:
pipeState = read32(PIPE_DDI_FUNC_CTL_B);
break;
case 2:
pipeState = read32(PIPE_DDI_FUNC_CTL_C);
break;
default:
pipeState = read32(PIPE_DDI_FUNC_CTL_EDP);
break;
}
if ((((pipeState & PIPE_DDI_SELECT_MASK) >> PIPE_DDI_SELECT_SHIFT) + 1) == (uint32)PortIndex()) {
// See if the BIOS enabled our output as it indicates it's in use
if (pipeState & PIPE_DDI_FUNC_CTL_ENABLE) {
TRACE("%s: Connected\n", __func__);
return true;
}
}
}
// On laptops we always have an internal panel.. (this is on the eDP port)
if (gInfo->shared_info->device_type.IsMobile() && (PortIndex() == INTEL_PORT_E)) { if (gInfo->shared_info->device_type.IsMobile() && (PortIndex() == INTEL_PORT_E)) {
pipeState = read32(PIPE_DDI_FUNC_CTL_EDP);
TRACE("%s: PIPE_DDI_FUNC_CTL_EDP: 0x%" B_PRIx32 "\n", __func__, pipeState);
if (!(pipeState & PIPE_DDI_FUNC_CTL_ENABLE)) {
TRACE("%s: Laptop, but eDP port down: enabling port on pipe EDP\n", __func__);
//fixme: turn on port and power
write32(PIPE_DDI_FUNC_CTL_EDP, pipeState | PIPE_DDI_FUNC_CTL_ENABLE);
TRACE("%s: PIPE_DDI_FUNC_CTL_EDP after: 0x%" B_PRIx32 "\n", __func__,
read32(PIPE_DDI_FUNC_CTL_EDP));
}
if (gInfo->shared_info->has_vesa_edid_info) { if (gInfo->shared_info->has_vesa_edid_info) {
TRACE("%s: Laptop. Using VESA edid info\n", __func__); TRACE("%s: Laptop. Using VESA edid info\n", __func__);
memcpy(&fEDIDInfo, &gInfo->shared_info->vesa_edid_info, memcpy(&fEDIDInfo, &gInfo->shared_info->vesa_edid_info, sizeof(edid1_info));
sizeof(edid1_info));
if (fEDIDState != B_OK) { if (fEDIDState != B_OK) {
fEDIDState = B_OK; fEDIDState = B_OK;
// HasEDID now true // HasEDID now true
@@ -1766,6 +1749,62 @@ DigitalDisplayInterface::IsConnected()
TRACE("%s: Laptop. No EDID, but force enabled as we have a VBT\n", __func__); TRACE("%s: Laptop. No EDID, but force enabled as we have a VBT\n", __func__);
return true; return true;
} }
//should not happen:
TRACE("%s: No (panel) type info found, assuming not connected\n", __func__);
return false;
}
// scan all our non-eDP pipes to find the one connected to the current port and check it's enabled
for (uint32 pipeCnt = 0; pipeCnt < 3; pipeCnt++) {
switch (pipeCnt) {
case 1:
pipeState = read32(PIPE_DDI_FUNC_CTL_B);
break;
case 2:
pipeState = read32(PIPE_DDI_FUNC_CTL_C);
break;
default:
pipeState = read32(PIPE_DDI_FUNC_CTL_A);
break;
}
if ((((pipeState & PIPE_DDI_SELECT_MASK) >> PIPE_DDI_SELECT_SHIFT) + 1) == (uint32)PortIndex()) {
TRACE("%s: PIPE_DDI_FUNC_CTL nr %" B_PRIx32 ": 0x%" B_PRIx32 "\n", __func__, pipeCnt + 1, pipeState);
// See if the BIOS enabled our output as it indicates it's in use
if (pipeState & PIPE_DDI_FUNC_CTL_ENABLE) {
TRACE("%s: Connected\n", __func__);
return true;
}
}
}
if (edidDetected) {
for (uint32 pipeCnt = 0; pipeCnt < 3; pipeCnt++) {
uint32 pipeReg = 0;
switch (pipeCnt) {
case 1:
pipeReg = PIPE_DDI_FUNC_CTL_B;
break;
case 2:
pipeReg = PIPE_DDI_FUNC_CTL_C;
break;
default:
pipeReg = PIPE_DDI_FUNC_CTL_A;
break;
}
pipeState = read32(pipeReg);
if (!(pipeState & PIPE_DDI_FUNC_CTL_ENABLE)) {
TRACE("%s: Connected but port down: enabling port on pipe nr %" B_PRIx32 "\n", __func__, pipeCnt + 1);
//fixme: turn on port and power
pipeState |= PIPE_DDI_FUNC_CTL_ENABLE;
pipeState &= ~PIPE_DDI_SELECT_MASK;
pipeState |= (((uint32)PortIndex()) - 1) << PIPE_DDI_SELECT_SHIFT;
//fixme: set mode to DVI mode for now (b26..24 = %001)
write32(pipeReg, pipeState);
TRACE("%s: PIPE_DDI_FUNC_CTL after: 0x%" B_PRIx32 "\n", __func__, read32(pipeReg));
return true;
}
}
TRACE("%s: No pipe available, ignoring connected screen\n", __func__);
} }
TRACE("%s: Not connected\n", __func__); TRACE("%s: Not connected\n", __func__);
@@ -143,7 +143,11 @@ init_common(int device, bool isClone)
gInfo->pipe_count = 0; gInfo->pipe_count = 0;
// Allocate all of our pipes // Allocate all of our pipes
for (int i = 0; i < MAX_PIPES; i++) { int pipeCnt = 2;
if (gInfo->shared_info->device_type.Generation() >= 7)
pipeCnt = 3; // some newer gens have even more..
for (int i = 0; i < pipeCnt; i++) {
switch (i) { switch (i) {
case 0: case 0:
gInfo->pipes[i] = new(std::nothrow) Pipe(INTEL_PIPE_A); gInfo->pipes[i] = new(std::nothrow) Pipe(INTEL_PIPE_A);
@@ -151,6 +155,9 @@ init_common(int device, bool isClone)
case 1: case 1:
gInfo->pipes[i] = new(std::nothrow) Pipe(INTEL_PIPE_B); gInfo->pipes[i] = new(std::nothrow) Pipe(INTEL_PIPE_B);
break; break;
case 2:
gInfo->pipes[i] = new(std::nothrow) Pipe(INTEL_PIPE_C);
break;
default: default:
ERROR("%s: Unknown pipe %d\n", __func__, i); ERROR("%s: Unknown pipe %d\n", __func__, i);
} }