intel_extreme: added more pipeC support, fixes for eDP on DDI systems
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user