intel_extreme: haswell and skylake DDI EDID support added, modesetting not finished yet.
This commit is contained in:
parent
3457006a9a
commit
661732341f
@ -847,7 +847,7 @@ struct intel_free_graphics_memory {
|
||||
|
||||
#define SNB_DPLL_SEL (0x7000 | REGS_SOUTH_SHARED)
|
||||
|
||||
// i2c
|
||||
// i2c bit banging interface
|
||||
#define INTEL_I2C_IO_A (0x5010 | REGS_SOUTH_SHARED)
|
||||
#define INTEL_I2C_IO_B (0x5014 | REGS_SOUTH_SHARED)
|
||||
#define INTEL_I2C_IO_C (0x5018 | REGS_SOUTH_SHARED)
|
||||
@ -856,6 +856,9 @@ struct intel_free_graphics_memory {
|
||||
#define INTEL_I2C_IO_F (0x5024 | REGS_SOUTH_SHARED)
|
||||
#define INTEL_I2C_IO_G (0x5028 | REGS_SOUTH_SHARED)
|
||||
#define INTEL_I2C_IO_H (0x502c | REGS_SOUTH_SHARED)
|
||||
// i2c hardware controller
|
||||
#define INTEL_GMBUS0 (0x5100 | REGS_SOUTH_SHARED)
|
||||
#define INTEL_GMBUS4 (0x5110 | REGS_SOUTH_SHARED)
|
||||
|
||||
#define I2C_CLOCK_DIRECTION_MASK (1 << 0)
|
||||
#define I2C_CLOCK_DIRECTION_OUT (1 << 1)
|
||||
@ -869,6 +872,15 @@ struct intel_free_graphics_memory {
|
||||
#define I2C_DATA_VALUE_IN (1 << 12)
|
||||
#define I2C_RESERVED ((1 << 13) | (1 << 5))
|
||||
|
||||
// gpu block clock gating disable bits
|
||||
#define INTEL_DSPCLK_GATE_D (0x2020 | REGS_SOUTH_SHARED)
|
||||
#define PCH_GMBUSUNIT_CLK_GATE_DIS (1UL << 31)
|
||||
#define INTEL_GEN9_CLKGATE_DIS_4 (0x653c | REGS_NORTH_SHARED)
|
||||
#define BXT_GMBUSUNIT_CLK_GATE_DIS (1 << 14)
|
||||
|
||||
// gpu power wells
|
||||
#define INTEL_PWR_WELL_CTL_2 (0x5404 | REGS_NORTH_SHARED)
|
||||
|
||||
// TODO: on IronLake this is in the north shared block at 0x41000
|
||||
#define INTEL_VGA_DISPLAY_CONTROL (0x1400 | REGS_NORTH_PLANE_CONTROL)
|
||||
#define VGA_DISPLAY_DISABLED (1UL << 31)
|
||||
|
@ -76,7 +76,8 @@ Pipe::Pipe(pipe_index pipeIndex)
|
||||
// IvyBridge: Analog + Digital Ports behind FDI (on northbridge)
|
||||
// Haswell: Only VGA behind FDI (on northbridge)
|
||||
// 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)) {
|
||||
TRACE("%s: Pipe %s routed through FDI\n", __func__,
|
||||
(pipeIndex == INTEL_PIPE_A) ? "A" : "B");
|
||||
|
||||
|
@ -291,18 +291,22 @@ Port::_SetI2CSignals(void* cookie, int clock, int data)
|
||||
value = read32(ioRegister) & I2C_RESERVED;
|
||||
}
|
||||
|
||||
// if we send clk or data, we always send low logic level;
|
||||
// if we want to send high level, we actually receive and let the
|
||||
// external pullup resistors create the high level on the bus.
|
||||
value |= I2C_DATA_VALUE_MASK; //sets data = 0, always latch
|
||||
value |= I2C_CLOCK_VALUE_MASK; //sets clock = 0, always latch
|
||||
|
||||
if (data != 0)
|
||||
value |= I2C_DATA_DIRECTION_MASK;
|
||||
else {
|
||||
value |= I2C_DATA_DIRECTION_MASK | I2C_DATA_DIRECTION_OUT
|
||||
| I2C_DATA_VALUE_MASK;
|
||||
value |= I2C_DATA_DIRECTION_MASK | I2C_DATA_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
if (clock != 0)
|
||||
value |= I2C_CLOCK_DIRECTION_MASK;
|
||||
else {
|
||||
value |= I2C_CLOCK_DIRECTION_MASK | I2C_CLOCK_DIRECTION_OUT
|
||||
| I2C_CLOCK_VALUE_MASK;
|
||||
value |= I2C_CLOCK_DIRECTION_MASK | I2C_CLOCK_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
write32(ioRegister, value);
|
||||
@ -1142,10 +1146,12 @@ DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode)
|
||||
PanelFitter* fitter = fPipe->PFT();
|
||||
if (fitter != NULL)
|
||||
fitter->Enable(*target);
|
||||
FDILink* link = fPipe->FDI();
|
||||
if (link != NULL)
|
||||
link->Train(target);
|
||||
|
||||
// skip FDI if it doesn't exist
|
||||
if (gInfo->shared_info->device_type.Generation() <= 8) {
|
||||
FDILink* link = fPipe->FDI();
|
||||
if (link != NULL)
|
||||
link->Train(target);
|
||||
}
|
||||
pll_divisors divisors;
|
||||
compute_pll_divisors(target, &divisors, false);
|
||||
|
||||
@ -1192,6 +1198,7 @@ EmbeddedDisplayPort::IsConnected()
|
||||
TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(),
|
||||
portRegister);
|
||||
|
||||
// fixme: Skylake and up use eDP for a seperate active VGA converter chip sometimes.
|
||||
if (!gInfo->shared_info->device_type.IsMobile()) {
|
||||
TRACE("%s: skipping eDP on non-mobile GPU\n", __func__);
|
||||
return false;
|
||||
@ -1249,7 +1256,17 @@ DigitalDisplayInterface::_PortRegister()
|
||||
addr_t
|
||||
DigitalDisplayInterface::_DDCRegister()
|
||||
{
|
||||
// TODO: No idea, does DDI have DDC?
|
||||
switch (PortIndex()) {
|
||||
case INTEL_PORT_B:
|
||||
return INTEL_I2C_IO_E;
|
||||
case INTEL_PORT_C:
|
||||
return INTEL_I2C_IO_D;
|
||||
case INTEL_PORT_D:
|
||||
return INTEL_I2C_IO_F;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1257,6 +1274,10 @@ DigitalDisplayInterface::_DDCRegister()
|
||||
status_t
|
||||
DigitalDisplayInterface::Power(bool enabled)
|
||||
{
|
||||
if (fPipe == NULL) {
|
||||
ERROR("%s: Setting power without assigned pipe!\n", __func__);
|
||||
return B_ERROR;
|
||||
}
|
||||
TRACE("%s: %s DDI enabled: %s\n", __func__, PortName(),
|
||||
enabled ? "true" : "false");
|
||||
|
||||
@ -1283,11 +1304,6 @@ DigitalDisplayInterface::IsConnected()
|
||||
if (portRegister == 0)
|
||||
return false;
|
||||
|
||||
if ((read32(portRegister) & DDI_INIT_DISPLAY_DETECTED) == 0) {
|
||||
TRACE("%s: %s link not detected\n", __func__, PortName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Probe a little port info.
|
||||
if ((read32(DDI_BUF_CTL_A) & DDI_A_4_LANES) != 0) {
|
||||
switch (PortIndex()) {
|
||||
@ -1318,7 +1334,6 @@ DigitalDisplayInterface::IsConnected()
|
||||
TRACE("%s: %s Maximum Lanes: %" B_PRId8 "\n", __func__,
|
||||
PortName(), fMaxLanes);
|
||||
|
||||
//DDI and also its EDID do not work yet, we fail on purpose as a workaround for now
|
||||
return HasEDID();
|
||||
}
|
||||
|
||||
@ -1339,11 +1354,14 @@ DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode)
|
||||
PanelFitter* fitter = fPipe->PFT();
|
||||
if (fitter != NULL)
|
||||
fitter->Enable(target->timing);
|
||||
// Skip FDI if we have a CPU connected display
|
||||
if (PortIndex() != INTEL_PORT_A) {
|
||||
FDILink* link = fPipe->FDI();
|
||||
if (link != NULL)
|
||||
link->Train(&target->timing);
|
||||
// skip FDI if it doesn't exist
|
||||
if (gInfo->shared_info->device_type.Generation() <= 8) {
|
||||
// Skip FDI if we have a CPU connected display
|
||||
if (PortIndex() != INTEL_PORT_A) {
|
||||
FDILink* link = fPipe->FDI();
|
||||
if (link != NULL)
|
||||
link->Train(&target->timing);
|
||||
}
|
||||
}
|
||||
|
||||
pll_divisors divisors;
|
||||
|
@ -255,6 +255,21 @@ probe_ports()
|
||||
bool foundDDI = false;
|
||||
|
||||
gInfo->port_count = 0;
|
||||
#if 0
|
||||
// make sure I2C hardware controller is off (we use bit-banging)
|
||||
if (gInfo->shared_info->device_type.Generation() >= 5) {
|
||||
write32(INTEL_DSPCLK_GATE_D,
|
||||
read32(INTEL_DSPCLK_GATE_D) | PCH_GMBUSUNIT_CLK_GATE_DIS);
|
||||
read32(INTEL_DSPCLK_GATE_D);
|
||||
|
||||
write32(INTEL_GEN9_CLKGATE_DIS_4,
|
||||
read32(INTEL_GEN9_CLKGATE_DIS_4) | BXT_GMBUSUNIT_CLK_GATE_DIS);
|
||||
read32(INTEL_GEN9_CLKGATE_DIS_4);
|
||||
|
||||
write32(INTEL_GMBUS0, 0); //reset, idle
|
||||
write32(INTEL_GMBUS4, 0); //block interrupts
|
||||
}
|
||||
#endif
|
||||
|
||||
// Display Port
|
||||
if (!gInfo->shared_info->device_type.HasDDI()) {
|
||||
@ -272,9 +287,9 @@ probe_ports()
|
||||
}
|
||||
}
|
||||
|
||||
// Digital Display Interface
|
||||
// Digital Display Interface (for DP, HDMI and DVI)
|
||||
if (gInfo->shared_info->device_type.HasDDI()) {
|
||||
for (int i = INTEL_PORT_A; i <= INTEL_PORT_E; i++) {
|
||||
for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) {
|
||||
TRACE("Probing DDI %d\n", i);
|
||||
|
||||
Port* ddiPort
|
||||
@ -292,6 +307,7 @@ probe_ports()
|
||||
}
|
||||
|
||||
// Ensure DP_A isn't already taken (or DDI)
|
||||
// Please note that Skylake and up use eDP for a seperate active VGA converter chip.
|
||||
TRACE("Probing eDP\n");
|
||||
if (!has_connected_port((port_index)INTEL_PORT_A, INTEL_PORT_TYPE_ANY)) {
|
||||
// also always try eDP, it'll also just fail if not applicable
|
||||
@ -304,64 +320,72 @@ probe_ports()
|
||||
delete eDPPort;
|
||||
}
|
||||
|
||||
for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) {
|
||||
TRACE("Probing HDMI %d\n", i);
|
||||
if (has_connected_port((port_index)i, INTEL_PORT_TYPE_ANY)) {
|
||||
// Ensure port not already claimed by something like DDI
|
||||
TRACE("Port already claimed\n");
|
||||
continue;
|
||||
}
|
||||
if (!gInfo->shared_info->device_type.HasDDI()) {
|
||||
for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) {
|
||||
TRACE("Probing HDMI %d\n", i);
|
||||
if (has_connected_port((port_index)i, INTEL_PORT_TYPE_ANY)) {
|
||||
// Ensure port not already claimed by something like DDI
|
||||
TRACE("Port already claimed\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
Port* hdmiPort = new(std::nothrow) HDMIPort((port_index)i);
|
||||
if (hdmiPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (hdmiPort->IsConnected())
|
||||
gInfo->ports[gInfo->port_count++] = hdmiPort;
|
||||
else
|
||||
delete hdmiPort;
|
||||
}
|
||||
|
||||
// always try the LVDS port, it'll simply fail if not applicable
|
||||
TRACE("Probing LVDS\n");
|
||||
Port* lvdsPort = new(std::nothrow) LVDSPort();
|
||||
if (lvdsPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
if (lvdsPort->IsConnected()) {
|
||||
foundLVDS = true;
|
||||
gInfo->ports[gInfo->port_count++] = lvdsPort;
|
||||
gInfo->head_mode |= HEAD_MODE_LVDS_PANEL;
|
||||
gInfo->head_mode |= HEAD_MODE_B_DIGITAL;
|
||||
} else
|
||||
delete lvdsPort;
|
||||
|
||||
if (!has_connected_port(INTEL_PORT_ANY, INTEL_PORT_TYPE_ANY)) {
|
||||
TRACE("Probing DVI\n");
|
||||
// there's neither DisplayPort nor HDMI so far, assume DVI B
|
||||
for (port_index index = INTEL_PORT_B; index <= INTEL_PORT_C;
|
||||
index = (port_index)(index + 1)) {
|
||||
Port* dviPort = new(std::nothrow) DigitalPort(index, "DVI");
|
||||
if (dviPort == NULL)
|
||||
Port* hdmiPort = new(std::nothrow) HDMIPort((port_index)i);
|
||||
if (hdmiPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (dviPort->IsConnected()) {
|
||||
gInfo->ports[gInfo->port_count++] = dviPort;
|
||||
gInfo->head_mode |= HEAD_MODE_B_DIGITAL;
|
||||
} else
|
||||
delete dviPort;
|
||||
if (hdmiPort->IsConnected())
|
||||
gInfo->ports[gInfo->port_count++] = hdmiPort;
|
||||
else
|
||||
delete hdmiPort;
|
||||
}
|
||||
}
|
||||
|
||||
// then finally always try the analog port
|
||||
TRACE("Probing Analog\n");
|
||||
Port* analogPort = new(std::nothrow) AnalogPort();
|
||||
if (analogPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
if (analogPort->IsConnected()) {
|
||||
gInfo->ports[gInfo->port_count++] = analogPort;
|
||||
gInfo->head_mode |= HEAD_MODE_A_ANALOG;
|
||||
} else
|
||||
delete analogPort;
|
||||
// always try the LVDS port when chipset supports it, it'll simply fail if not applicable
|
||||
if (!gInfo->shared_info->device_type.HasDDI()) {
|
||||
TRACE("Probing LVDS\n");
|
||||
Port* lvdsPort = new(std::nothrow) LVDSPort();
|
||||
if (lvdsPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
if (lvdsPort->IsConnected()) {
|
||||
foundLVDS = true;
|
||||
gInfo->ports[gInfo->port_count++] = lvdsPort;
|
||||
gInfo->head_mode |= HEAD_MODE_LVDS_PANEL;
|
||||
gInfo->head_mode |= HEAD_MODE_B_DIGITAL;
|
||||
} else
|
||||
delete lvdsPort;
|
||||
}
|
||||
|
||||
if (!gInfo->shared_info->device_type.HasDDI()) {
|
||||
if (!has_connected_port(INTEL_PORT_ANY, INTEL_PORT_TYPE_ANY)) {
|
||||
TRACE("Probing DVI\n");
|
||||
// there's neither DisplayPort nor HDMI so far, assume DVI B
|
||||
for (port_index index = INTEL_PORT_B; index <= INTEL_PORT_C;
|
||||
index = (port_index)(index + 1)) {
|
||||
Port* dviPort = new(std::nothrow) DigitalPort(index, "DVI");
|
||||
if (dviPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (dviPort->IsConnected()) {
|
||||
gInfo->ports[gInfo->port_count++] = dviPort;
|
||||
gInfo->head_mode |= HEAD_MODE_B_DIGITAL;
|
||||
} else
|
||||
delete dviPort;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// then finally always try the analog port when chipsets supports it
|
||||
if (gInfo->shared_info->device_type.Generation() <= 8) {
|
||||
TRACE("Probing Analog\n");
|
||||
Port* analogPort = new(std::nothrow) AnalogPort();
|
||||
if (analogPort == NULL)
|
||||
return B_NO_MEMORY;
|
||||
if (analogPort->IsConnected()) {
|
||||
gInfo->ports[gInfo->port_count++] = analogPort;
|
||||
gInfo->head_mode |= HEAD_MODE_A_ANALOG;
|
||||
} else
|
||||
delete analogPort;
|
||||
}
|
||||
|
||||
if (gInfo->port_count == 0)
|
||||
return B_ERROR;
|
||||
|
Loading…
x
Reference in New Issue
Block a user